├── LICENSE ├── README.md ├── __init__.py ├── browser └── chromedriver.exe ├── bus_factor_gui.py ├── bus_factor_gui.pyc ├── bus_factor_log ├── bus_factor_metric.py ├── bus_img.png ├── css ├── bootstrap │ ├── bootstrap-theme.css │ ├── bootstrap-theme.css.map │ ├── bootstrap-theme.min.css │ ├── bootstrap.css │ ├── bootstrap.css.map │ └── bootstrap.min.css └── style.css ├── data ├── dirs.json ├── extension_relevance.json ├── exts.json ├── files.json ├── project_info.json └── user_relevance.json ├── index.html ├── js ├── bootstrap │ ├── bootstrap.js │ └── bootstrap.min.js ├── d3.v3.min.js ├── initIndex.js └── vendor │ └── jquery.js ├── license.txt ├── results └── decidim │ ├── decidim-hosp-master-wdc.png │ ├── decidim-master-wdc.png │ └── decidim.zip ├── setup.py └── tool.py /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 valerio cosentino 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | [Except as contained in this notice, the name of valerio cosentino 23 | shall not be used in advertising or otherwise to promote the sale, use 24 | or other dealings in this Software without prior written authorization 25 | from valerio cosentino.] 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bus Factor Analyzer 2 | 3 | The tool is the result of the ongoing work published in the 22nd IEEE International Conference on Software Analysis, Evolution, and Reengineering (available for download at http://tinyurl.com/AssessingBusFactorForGitRepo). We would be very interested in getting feedback and helping people use it. 4 | 5 | ## How To 6 | 7 | In order to run the tool you need to perform some steps: 8 | 9 | 1) Install Gitana (https://github.com/valeriocos/Gitana) 10 | 11 | 2) Import your Git repository to Gitana, and export the file information to JSON 12 | ```python 13 | CONFIG = { 14 | 'user': 'root', 15 | 'password': 'root', 16 | 'host': 'localhost', 17 | 'port': '3306', 18 | 'raise_on_warnings': False, 19 | 'buffered': True 20 | } 21 | 22 | g = Gitana(CONFIG) 23 | g.init_db("YOUR-DB-NAME") 24 | g.create_project("YOUR-DB-NAME", "YOUR-PROJECT-NAME") 25 | g.import_git_data("YOUR-DB-NAME", "YOUR-PROJECT-NAME", "YOUR-REPO-NAME", "GIT-REPO-PATH") 26 | g.export_json("YOUR-DB-NAME", "YOUR-REPO-NAME", "OUTPUT-PATH", references=["origin/master"]) 27 | ``` 28 | 29 | 3) Launch the Bus Factor Analyzer GUI (https://github.com/valeriocos/BusFactor/blob/master/tool.py) 30 | 31 | ## Settings 32 | 33 | The Bus Factor Analyzer GUI allows you to tune the process to assess the bus factor for your Git repository. 34 | In particular you will be able to play with: 35 | 36 | ### Primary developer knowledge 37 | Primary developers are those developers that have modified a minimum percentage X of a software artifact (e.g., file, 38 | directory, branch, file extension) of the repository. By default, X is set to 1/D, where D is the overall number of developers that have ever 39 | modified the artifact. However, X can be changed to be, for instance, 1/2 (50% of the modifications over the artifact), 1/4 (25%) and so on. 40 | 41 | ### Secondary developer knowledge 42 | Secondary developers are those developers that know at least a proportion Y of what the primary developers know (X). By default, 43 | Y is set to half of X (0.5), however it can be changed to a value between 0 and 1. In case you don't want to use 44 | the secondary developer knowledge parameter, you can set Y to 1. 45 | 46 | ### Metric 47 | This parameter is used to combine the importance of the number and order of modifications to assign the knowledge value. 48 | Note that depending on the level of detail selected, the four metrics are initially calculated at file or line level (just for text files). 49 | Once the selected metric has been calculated, its calculation is repeated at each level of the repository to assign a bus factor value 50 | to each directory, branch, file extension and the repository itself. 51 | 52 | - **Last change.** This metric assigns all knowledge of a line/file to the last developer that modified that 53 | line (or file for binary files). 54 | 55 | - **Multiple changes.** This metric counts the number of times a line/file has been modified during the life-cycle of the project. 56 | It assigns more knowledge to the developers that modified the line/file most times. 57 | 58 | - **Distinct changes.** This metric assesses the developer knowledge according to the number of non-consecutive changes on the line/file. 59 | 60 | - **Weighted distinct changes.** This metric assesses the developer knowledge by relying of the previous metric modified to take into account the position of the 61 | modifications in the time-line evolution of the line/file. It is used to assign an incremental importance to the later modifications 62 | on the line/file. 63 | 64 | ## Demo 65 | 66 | A demo of the tool is available at https://github.com/atlanmod/busfactor_demo 67 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'valerio cosentino' 2 | -------------------------------------------------------------------------------- /browser/chromedriver.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SOM-Research/busfactor/dd83df584dac523b259a5b897724dc78df01037a/browser/chromedriver.exe -------------------------------------------------------------------------------- /bus_factor_gui.py: -------------------------------------------------------------------------------- 1 | __author__ = 'atlanmod' 2 | 3 | from bus_factor_metric import Metrics 4 | from Tkinter import * 5 | from tkFileDialog import * 6 | import ttk 7 | import os 8 | import tkMessageBox 9 | import shutil 10 | import logging 11 | import getopt 12 | import threading 13 | import re 14 | import traceback 15 | from PIL import ImageTk, Image 16 | 17 | class BusFactor(Tk): 18 | 19 | LOG_FILENAME = "bus_factor_log" 20 | NOTIFICATION = "bus_factor_notification" 21 | 22 | def __init__(self, notify): 23 | Tk.__init__(self) 24 | self.mypath = os.path.dirname(os.path.abspath(__file__)) + "/" 25 | 26 | self.logger = logging.getLogger('bus_factor') 27 | fileHandler = logging.FileHandler(BusFactor.LOG_FILENAME, mode='w') 28 | formatter = logging.Formatter("%(asctime)s:%(levelname)s:%(message)s", "%Y-%m-%d %H:%M:%S") 29 | fileHandler.setFormatter(formatter) 30 | 31 | self.logger.setLevel(logging.INFO) 32 | self.logger.addHandler(fileHandler) 33 | 34 | self.NOTIFY = notify 35 | 36 | self.JSON_PATH = "" 37 | self.initialize_gui() 38 | self.title("Bus Factor Calculator") 39 | self.mainloop() 40 | 41 | def search_for_resource(self): 42 | f = askopenfilename(parent=self, title='Choose a file', 43 | filetypes=[("JSON files", "*.json")]) 44 | self.JSONPathVariable.set(f) 45 | 46 | def initialize_gui(self): 47 | 48 | img = Image.open(self.mypath + "bus_img.png") 49 | img = img.resize((250, 250), Image.ANTIALIAS) 50 | img = ImageTk.PhotoImage(img) 51 | 52 | labelImg = Label(image=img) 53 | labelImg.image = img 54 | labelImg.grid(row=0, columnspan=2, rowspan=2, sticky='WE') 55 | 56 | ########################## 57 | #select repo 58 | labelJSONPath = Label(self, text=u"JSON Path", anchor="w") 59 | labelJSONPath.grid(column=0, row=3, sticky='W') 60 | 61 | self.JSONPathVariable = StringVar() 62 | self.entryJSONPath = Entry(self, textvariable=self.JSONPathVariable, width=40) 63 | self.entryJSONPath.grid(column=1, row=3, sticky='W') 64 | 65 | buttonSearchJSON = Button(self, text=u"search", command=self.search_for_resource) 66 | buttonSearchJSON.grid(column=2, row=3, sticky="E") 67 | 68 | ########################## 69 | #empty label 70 | emptyLabel = Label(self, anchor="w") 71 | emptyLabel.grid(column=0, row=4, sticky='WE') 72 | 73 | ########################## 74 | #Tuning label 75 | labelTuning = Label(self, text=u"Tuning:", anchor="w") 76 | labelTuning.grid(column=0, row=5, sticky='WE') 77 | 78 | #Primary expert knowledge 79 | labelPrimaryExpertKnowledge = Label(self, text=u"Primary Dev. Knowl.", anchor="w") 80 | labelPrimaryExpertKnowledge.grid(column=0, row=6, sticky='W') 81 | 82 | self.labelPrimaryExpertKnowledgeVariable = StringVar() 83 | entryLabelPrimaryExpertKnowledge = Entry(self, textvariable=self.labelPrimaryExpertKnowledgeVariable) 84 | self.labelPrimaryExpertKnowledgeVariable.set("1/D") 85 | entryLabelPrimaryExpertKnowledge.grid(column=1, row=6, sticky='W') 86 | 87 | #Secondary Expert knowledge proportion 88 | labelSecondaryExpertProportion = Label(self, text=u"Secondary Dev. Knowl. Prop.", anchor="w") 89 | labelSecondaryExpertProportion.grid(column=0, row=7, sticky='W') 90 | 91 | self.labelSecondaryExpertProportionVariable = StringVar() 92 | entryLabelSecondaryExpertProportion = Entry(self, textvariable=self.labelSecondaryExpertProportionVariable) 93 | self.labelSecondaryExpertProportionVariable.set("0.5") 94 | entryLabelSecondaryExpertProportion.grid(column=1, row=7, sticky='W') 95 | 96 | #detail level 97 | self.detailLevelVariable = StringVar() 98 | labelDetailLevel = Label(self, text=u"Detail Level", anchor="w") 99 | labelDetailLevel.grid(column=0, row=8, sticky='W') 100 | 101 | self.detailLevelComboBox = ttk.Combobox(self, textvariable=self.detailLevelVariable) 102 | self.detailLevelComboBox['values'] = ('file') 103 | self.detailLevelComboBox.current(0) 104 | self.detailLevelComboBox.grid(column=1, row=8, sticky='W') 105 | 106 | 107 | #metric 108 | labelMetric = Label(self, text=u"Metric", anchor="w") 109 | labelMetric.grid(column=0, row=9, sticky='W') 110 | 111 | self.metricComboBoxVariable = StringVar() 112 | self.metricComboBox = ttk.Combobox(self, textvariable=self.metricComboBoxVariable) 113 | self.metricComboBox['values'] = ('last change', 'multiple changes', 'distinct changes', 'weighted distinct changes') 114 | self.metricComboBox.current(0) 115 | self.metricComboBox.grid(column=1, row=9, sticky='W') 116 | 117 | #Finish button 118 | self.buttonFinish = Button(self, text=u"Execute", command=self.launch_thread_execute) 119 | self.buttonFinish.grid(column=1, row=10, sticky="E") 120 | 121 | #Abort interrupt 122 | self.buttonAbort = Button(self, text=u"Abort", command=self.launch_thread_interrupt) 123 | self.buttonAbort.grid(column=2, row=10, sticky="E") 124 | self.buttonAbort.config(state=DISABLED) 125 | 126 | self.info_execution = StringVar() 127 | labelExecuting = Label(self, textvariable=self.info_execution, anchor="w") 128 | labelExecuting.grid(column=0, row=10, sticky='EW') 129 | 130 | self.resizable(True, False) 131 | 132 | # TKinker is not thread safe! 133 | # See http://stackoverflow.com/questions/22541693/tkinter-and-thread-out-of-stack-space-infinite-loop 134 | self.resetButtons = False 135 | self.importingFailureMsg = "" 136 | def do_every_50_ms(self): 137 | if self.resetButtons: 138 | self.buttonFinish.config(state=NORMAL) 139 | self.buttonAbort.config(state=DISABLED) 140 | self.resetButtons = False 141 | if self.importingFailureMsg: 142 | tkMessageBox.showerror("Execution failed:", 143 | self.importingFailureMsg) 144 | self.importingFailureMsg = "" 145 | self.after(50, do_every_50_ms, self) 146 | do_every_50_ms(self) 147 | 148 | def search_for_directory(self): 149 | dir = askdirectory(parent=self, title='Choose a directory') 150 | self.repoPathVariable.set(dir) 151 | try: 152 | repoName = dir.split('/')[-1] 153 | self.repoNameVariable.set(re.sub(r'\W', '', repoName).lower()) 154 | except: 155 | try: 156 | repoName = dir.split('\\')[-1] 157 | self.repoNameVariable.set(re.sub(r'\W', '', repoName).lower()) 158 | except: 159 | repoName = '' 160 | 161 | def search_for_resource(self): 162 | f = askopenfilename(parent=self, title='Choose a file', 163 | filetypes=[("Forbidden-resource files", "*.json")]) 164 | self.JSONPathVariable.set(f) 165 | 166 | def check_path_existance(self, string): 167 | flag = True 168 | if not os.path.exists(string): 169 | flag = False 170 | return flag 171 | 172 | def launch_thread_interrupt(self): 173 | self.buttonFinish.config(state=DISABLED) 174 | self.buttonAbort.config(state=NORMAL) 175 | self.thread_interrupt = threading.Thread(target=self.interrupt) 176 | self.thread_interrupt.daemon = True 177 | self.thread_interrupt.start() 178 | self.thread_interrupt.join() 179 | 180 | def launch_thread_execute(self): 181 | self.info_execution.set("Executing...") 182 | self.buttonFinish.config(state=DISABLED) 183 | self.buttonAbort.config(state=NORMAL) 184 | self.thread_execute = threading.Thread(target=self.validator) 185 | self.thread_execute.daemon = True 186 | self.thread_execute.start() 187 | 188 | def interrupt(self): 189 | self.info_execution.set("Aborting...") 190 | sys.exc_clear() 191 | sys.exc_traceback = sys.last_traceback = None 192 | os._exit(-1) 193 | 194 | def validator(self): 195 | flag = True 196 | if self.JSONPathVariable.get() == "": 197 | self.JSONPathVariable.set("path cannot be empty!") 198 | flag = False 199 | else: 200 | if not self.check_path_existance(self.JSONPathVariable.get()): 201 | self.repoPathVariable.set("not valid path!") 202 | flag = False 203 | 204 | if self.labelPrimaryExpertKnowledgeVariable.get() == "": 205 | self.labelPrimaryExpertKnowledgeVariable.set("cannot be empty!") 206 | flag = False 207 | else: 208 | if self.labelPrimaryExpertKnowledgeVariable.get() != "1/D": 209 | try: 210 | value = float(self.labelPrimaryExpertKnowledgeVariable.get()) 211 | if value < 0 or value >= 1: 212 | self.labelPrimaryExpertKnowledgeVariable.set("(0,1] || 1/D") 213 | flag = False 214 | except: 215 | self.labelPrimaryExpertKnowledgeVariable.set("(0,1] || 1/D") 216 | flag = False 217 | 218 | 219 | if self.labelSecondaryExpertProportionVariable.get() == "": 220 | self.labelSecondaryExpertProportionVariable.set("cannot be empty!") 221 | flag = False 222 | else: 223 | try: 224 | value = float(self.labelSecondaryExpertProportionVariable.get()) 225 | if value < 0 or value >= 1: 226 | self.labelSecondaryExpertProportionVariable.set("(0,1]") 227 | flag = False 228 | except: 229 | flag = False 230 | self.labelSecondaryExpertProportionVariable.set("(0,1]") 231 | 232 | if flag: 233 | try: 234 | self.execute_process() 235 | except: 236 | print traceback.format_exc() 237 | self.info_execution.set("Failed") 238 | #self.buttonFinish.config(state=NORMAL) 239 | #self.buttonAbort.config(state=DISABLED) 240 | self.importingFailureMsg = traceback.format_exc(limit=1) 241 | self.resetButtons = True 242 | 243 | def execute_process(self): 244 | self.init_process() 245 | self.start_process() 246 | self.notify() 247 | self.info_execution.set("Finished") 248 | #self.buttonFinish.config(state=NORMAL) 249 | #self.buttonAbort.config(state=DISABLED) 250 | self.resetButtons = True 251 | 252 | def notify(self): 253 | if self.NOTIFY: 254 | notified = open(self.NOTIFICATION, "w") 255 | notified.close() 256 | sys.exc_clear() 257 | sys.exc_traceback = sys.last_traceback = None 258 | return 259 | 260 | def start_process(self): 261 | input_json = self.JSONPathVariable.get() 262 | 263 | output_json = self.OUTPUT_DIRECTORY 264 | metrics = Metrics(input_json, output_json, 265 | self.DEVELOPER_KNOWLEDGE_STRATEGY, 266 | self.PRIMARY_EXPERT_KNOWLEDGE, 267 | self.SECONDARY_EXPERT_KNOWLEDGE_PROPORTION, self.logger) 268 | metrics.export_bus_factor_information() 269 | 270 | def init_process(self): 271 | self.OUTPUT_DIRECTORY = "./data/" 272 | self.JSON_PATH = self.JSONPathVariable.get() 273 | 274 | self.LINE_DETAILS = False 275 | 276 | if self.labelPrimaryExpertKnowledgeVariable.get() == "1/D": 277 | self.PRIMARY_EXPERT_KNOWLEDGE = "default" 278 | else: 279 | self.PRIMARY_EXPERT_KNOWLEDGE = self.labelPrimaryExpertKnowledgeVariable.get() 280 | 281 | if self.labelSecondaryExpertProportionVariable.get() == "0.5": 282 | self.SECONDARY_EXPERT_KNOWLEDGE_PROPORTION = "default" 283 | else: 284 | self.SECONDARY_EXPERT_KNOWLEDGE_PROPORTION = self.labelSecondaryExpertProportionVariable.get() 285 | 286 | self.DEVELOPER_KNOWLEDGE_STRATEGY = self.metricComboBoxVariable.get().replace(' ', '_') 287 | 288 | #create output directories 289 | if os.path.exists(self.OUTPUT_DIRECTORY): 290 | shutil.rmtree(self.OUTPUT_DIRECTORY) 291 | os.makedirs(self.OUTPUT_DIRECTORY) 292 | 293 | 294 | def main(argv): 295 | notify = False 296 | try: 297 | opts, args = getopt.getopt(argv, "hn", ["notify="]) 298 | except getopt.GetoptError: 299 | print 'bus_factor_gui.py -n ' 300 | sys.exit(2) 301 | for opt, arg in opts: 302 | if opt in ('-h', '--help'): 303 | print 'bus_factor_gui.py -n ' 304 | sys.exit() 305 | elif opt in ("-n", "--notify"): 306 | notify = bool(args[0]) 307 | #if notify is true, a file is generate after the bus factor calculation to notify tool.py 308 | BusFactor(notify) 309 | 310 | if __name__ == "__main__": 311 | main(sys.argv[1:]) 312 | -------------------------------------------------------------------------------- /bus_factor_gui.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SOM-Research/busfactor/dd83df584dac523b259a5b897724dc78df01037a/bus_factor_gui.pyc -------------------------------------------------------------------------------- /bus_factor_log: -------------------------------------------------------------------------------- 1 | 2017-07-12 11:42:33:INFO:bus factor metric: process finished after 0.0 minutes and 1.2 secs 2 | -------------------------------------------------------------------------------- /bus_factor_metric.py: -------------------------------------------------------------------------------- 1 | __author__ = 'atlanmod' 2 | 3 | from datetime import datetime 4 | import simplejson as json 5 | import codecs 6 | import re 7 | 8 | class Metrics(): 9 | 10 | DEFAULT = "default" 11 | 12 | def __init__(self, json_repo_path, json_bus_factor_dir, bus_factor_calculation, 13 | primary_expert_knowledge, 14 | secondary_expert_knowledge_proportion, logger): 15 | self.logger = logger 16 | self.JSON_REPO_PATH = json_repo_path 17 | self.JSON_BUS_FACTOR_DIR = json_bus_factor_dir 18 | 19 | self.USERS = set() 20 | self.TOTAL_FILES = 0 21 | self.EXTENSIONS = {} 22 | 23 | #last_change 24 | #multiple_changes 25 | #distinct_changes 26 | #weighted_distinct_changes 27 | self.DEVELOPER_KNOWLEDGE_CALCULATION = bus_factor_calculation 28 | 29 | if primary_expert_knowledge != self.DEFAULT: 30 | self.PRIMARY_EXPERT_KNOWLEDGE_PROPORTION = primary_expert_knowledge 31 | else: 32 | self.PRIMARY_EXPERT_KNOWLEDGE_PROPORTION = self.DEFAULT 33 | 34 | if secondary_expert_knowledge_proportion == self.DEFAULT: 35 | self.SECONDARY_EXPERT_KNOWLEDGE_PROPORTION = 0.5 36 | else: 37 | self.SECONDARY_EXPERT_KNOWLEDGE_PROPORTION = secondary_expert_knowledge_proportion 38 | 39 | def get_sorted_keys(self, dictionary): 40 | return sorted(dictionary, key=dictionary.get, reverse=True) 41 | 42 | def get_developer_knowledge_percentage(self, authors2changes): 43 | number_of_changes = sum(authors2changes.values()) 44 | 45 | developer_knowledge_percentage = {} 46 | for k in authors2changes.keys(): 47 | percentage_author_changes = round((authors2changes.get(k)/float(number_of_changes))*100, 2) 48 | developer_knowledge_percentage.update({k: percentage_author_changes}) 49 | 50 | return developer_knowledge_percentage 51 | 52 | #get the authors that made more modifications on a part of code (ex.: line, file) 53 | #A primary expert is an author that has modified more than 1/N percentage of the file, where N is the number of authors that modified the file 54 | def get_primary_experts(self, authors2changes): 55 | primary_experts = [] 56 | developers_knowledge_percentage = self.get_developer_knowledge_percentage(authors2changes) 57 | developers_knowledge_percentage_sorted_keys = self.get_sorted_keys(developers_knowledge_percentage) 58 | 59 | number_of_authors = len(authors2changes.keys()) 60 | 61 | if self.PRIMARY_EXPERT_KNOWLEDGE_PROPORTION == self.DEFAULT: 62 | primary_expert_proportion = 1/float(number_of_authors) 63 | else: 64 | primary_expert_proportion = self.PRIMARY_EXPERT_KNOWLEDGE_PROPORTION 65 | 66 | primary_expertise_threshold = round(primary_expert_proportion*100, 2) 67 | 68 | for k in developers_knowledge_percentage_sorted_keys: 69 | if developers_knowledge_percentage.get(k) >= primary_expertise_threshold: 70 | primary_experts.append((k, developers_knowledge_percentage.get(k))) 71 | else: 72 | break 73 | 74 | return primary_experts 75 | 76 | #get the bus factor for a file 77 | #The bus factor is calculate according to the primary experts of the files plus the authors that hold at least half of the knowledge of the primary experts 78 | #If there are more than one primary experts, the bus factor will include the authors that have more than the average of the primary experts' percentage 79 | #Ex.: if the primary experts own 60% of the file, an author to be considered a secondary expert part of the bus factor should hold at least the 30% of the files 80 | def get_bus_factor_authors(self, authors2changes): 81 | experts_in_bus_factor = [] 82 | developer_knowledge_percentage = self.get_developer_knowledge_percentage(authors2changes) 83 | developer_knowledge_percentage_sorted_keys = self.get_sorted_keys(developer_knowledge_percentage) 84 | 85 | primary_experts = self.get_primary_experts(authors2changes) 86 | 87 | primary_expertise_percentage_value = 0 88 | for pe in primary_experts: 89 | primary_expertise_percentage_value = primary_expertise_percentage_value + pe[1] 90 | 91 | bus_factor_threshold = round((primary_expertise_percentage_value/len(primary_experts))*self.SECONDARY_EXPERT_KNOWLEDGE_PROPORTION, 2) 92 | 93 | for k in developer_knowledge_percentage_sorted_keys: 94 | if developer_knowledge_percentage.get(k) >= bus_factor_threshold: 95 | experts_in_bus_factor.append((k, developer_knowledge_percentage.get(k))) 96 | else: 97 | break 98 | 99 | return experts_in_bus_factor 100 | 101 | #calculate the developer knowledge of a line according to the position of the change in the history of the line 102 | #Ex.: A, B, D are 3 users: A -> B -> A -> B -> B -> D is converted to A -> B -> A -> B -> D and then 103 | # A x 1 -> B x 2 -> A x 3 -> B x 4 -> D x 5 so then A = 4, B = 6, D = 5 104 | def calculate_developer_knowledge_line_weighted_distinct_changes(self, line): 105 | #collect the number of changes per author for the line 106 | line_authors2changes = {} 107 | changes = line.get('line_changes') 108 | changes.reverse() 109 | previous_author = "" 110 | authors = [] 111 | #collect the authors 112 | for change in changes: 113 | author = change.get('author').get('name') 114 | if author != previous_author: 115 | authors.append(author) 116 | previous_author = author 117 | 118 | pos = 1 119 | for author in authors: 120 | if line_authors2changes.get(author): 121 | number_of_changes = line_authors2changes.get(author) 122 | line_authors2changes.update({author: number_of_changes+pos}) 123 | else: 124 | line_authors2changes.update({author: pos}) 125 | pos += 1 126 | 127 | return line_authors2changes 128 | 129 | #calculate the developer knowledge of the line according to the last change on the line 130 | #Ex.: A and B are 2 users: A -> A -> A -> B 131 | def calculate_developer_knowledge_line_last_change(self, line): 132 | #collect the number of changes per author for the line 133 | line_authors2changes = {} 134 | changes = line.get('line_changes') 135 | author = changes[0].get('author').get('name') 136 | line_authors2changes.update({author: 1}) 137 | 138 | return line_authors2changes 139 | 140 | #calculate the developer knowledge of the line according to the number of distinct changes on the line. 141 | #Ex.: A and B are 2 users: A -> A -> A -> B is tranformed in A -> B, A -> A -> A -> B -> is trasformed in A -> B -> A 142 | def calculate_developer_knowledge_line_distinct_changes(self, line): 143 | #collect the number of changes per author for the line 144 | line_authors2changes = {} 145 | changes = line.get('line_changes') 146 | previous_author = "" 147 | for change in changes: 148 | author = change.get('author').get('name') 149 | if author != previous_author: 150 | if line_authors2changes.get(author): 151 | number_of_changes = line_authors2changes.get(author) 152 | line_authors2changes.update({author: number_of_changes+1}) 153 | else: 154 | line_authors2changes.update({author: 1}) 155 | previous_author = author 156 | 157 | return line_authors2changes 158 | 159 | 160 | #calculate the the developer knowledge of the line according to the number of times the lines has been modified. 161 | #Note that this way of calculating the developer knowledge will benefit the users used to rewrite a lot his own code 162 | def calculate_developer_knowledge_line_multiple_changes(self, line): 163 | #collect the number of changes per author for the line 164 | line_authors2changes = {} 165 | changes = line.get('line_changes') 166 | for change in changes: 167 | author = change.get('author').get('name') 168 | if line_authors2changes.get(author): 169 | number_of_changes = line_authors2changes.get(author) 170 | line_authors2changes.update({author: number_of_changes+1}) 171 | else: 172 | line_authors2changes.update({author: 1}) 173 | 174 | return line_authors2changes 175 | 176 | def calculate_developer_knowledge_line(self, line, type): 177 | if type == "last_change": 178 | line_authors2changes = self.calculate_developer_knowledge_line_last_change(line) 179 | elif type == "multiple_changes": 180 | line_authors2changes = self.calculate_developer_knowledge_line_multiple_changes(line) 181 | elif type == "distinct_changes": 182 | line_authors2changes = self.calculate_developer_knowledge_line_distinct_changes(line) 183 | elif type == "weighted_distinct_changes": 184 | line_authors2changes = self.calculate_developer_knowledge_line_weighted_distinct_changes(line) 185 | 186 | return line_authors2changes 187 | 188 | def update_file_authors2changes(self, line_authors2changes, file_authors2changes): 189 | for lo in line_authors2changes.keys(): 190 | if file_authors2changes.get(lo): 191 | times = file_authors2changes.get(lo) 192 | file_authors2changes.update({lo: times+line_authors2changes.get(lo)}) 193 | else: 194 | file_authors2changes.update({lo: line_authors2changes.get(lo)}) 195 | 196 | #calculate the file change authors according to the number of changes the performed on the file 197 | #Ex.: A and B are 2 users: A -> B -> A -> A -> A 198 | def calculate_developer_knowledge_file_change_multiple_changes(self, json_entry): 199 | file_authors2changes = {} 200 | changes = json_entry.get('file_changes') 201 | #collect the authors of the changes on the file 202 | for change in changes: 203 | author = change.get('author').get('name') 204 | if file_authors2changes.get(author): 205 | times = file_authors2changes.get(author) 206 | file_authors2changes.update({author: times+1}) 207 | else: 208 | file_authors2changes.update({author: 1}) 209 | 210 | return file_authors2changes 211 | 212 | #calculate the file change authors without considering the sequence of multiple changes an author could perform 213 | #Ex.: A and B are 2 users: A -> B -> A -> A -> A is transformed to A -> B -> A 214 | def calculate_developer_knowledge_file_change_distinct_changes(self, json_entry): 215 | file_authors2changes = {} 216 | changes = json_entry.get('file_changes') 217 | #collect the authors of the changes on the file 218 | previous_author = "" 219 | for change in changes: 220 | author = change.get('author').get('name') 221 | if author != previous_author: 222 | if file_authors2changes.get(author): 223 | times = file_authors2changes.get(author) 224 | file_authors2changes.update({author: times+1}) 225 | else: 226 | file_authors2changes.update({author: 1}) 227 | previous_author = author 228 | 229 | return file_authors2changes 230 | 231 | #calculate the file change authors considering only the last change 232 | def calculate_developer_knowledge_file_change_last_change(self, json_entry): 233 | file_authors2changes = {} 234 | change = json_entry.get('file_changes')[0] 235 | #collect the authors of the changes on the file 236 | file_authors2changes.update({change.get('author').get('name'): 1}) 237 | 238 | return file_authors2changes 239 | 240 | #calculate the file change authors according to the position of the change in the history of the file 241 | #Ex.: A, B, D are 3 users: A -> B -> A -> B -> B -> D is converted to A -> B -> A -> B -> D and then 242 | # A x 1 -> B x 2 -> A x 3 -> B x 4 -> D x 5 so then A = 4, B = 6, D = 5 243 | def calculate_developer_knowledge_file_change_weighted_distinct_changes(self, json_entry): 244 | file_authors2changes = {} 245 | changes = json_entry.get('file_changes') 246 | changes.reverse() 247 | #collect the authors of the changes on the file 248 | previous_author = "" 249 | authors = [] 250 | for change in changes: 251 | author = change.get('author').get('name') 252 | if author != previous_author: 253 | authors.append(author) 254 | previous_author = author 255 | 256 | pos = 1 257 | for author in authors: 258 | if file_authors2changes.get(author): 259 | number_of_changes = file_authors2changes.get(author) 260 | file_authors2changes.update({author: number_of_changes+pos}) 261 | else: 262 | file_authors2changes.update({author: pos}) 263 | pos += 1 264 | 265 | return file_authors2changes 266 | 267 | def calculate_developer_knowledge_file_change(self, json_entry, type): 268 | if type == "multiple_changes": 269 | file_authors2changes = self.calculate_developer_knowledge_file_change_multiple_changes(json_entry) 270 | elif type == "distinct_changes": 271 | file_authors2changes = self.calculate_developer_knowledge_file_change_distinct_changes(json_entry) 272 | elif type == "last_change": 273 | file_authors2changes = self.calculate_developer_knowledge_file_change_last_change(json_entry) 274 | elif type == "weighted_distinct_changes": 275 | file_authors2changes = self.calculate_developer_knowledge_file_change_weighted_distinct_changes(json_entry) 276 | 277 | return file_authors2changes 278 | 279 | def calculate_file_primary_experts(self, json_entry): 280 | file_authors2changes = {} 281 | lines = json_entry.get('lines') 282 | 283 | #if the file has lines 284 | if lines: 285 | for line in lines: 286 | line_author2changes = self.calculate_developer_knowledge_line(line, Metrics.OWNERSHIP_CALCULATION) 287 | self.update_file_authors2changes(line_author2changes, file_authors2changes) 288 | #if the file is an image, a binary files, etc. 289 | else: 290 | file_authors2changes = self.calculate_developer_knowledge_file_change(json_entry, Metrics.OWNERSHIP_CALCULATION) 291 | 292 | #get the file primary experts 293 | primary_experts = self.get_primary_experts(file_authors2changes) 294 | 295 | return primary_experts 296 | 297 | def calculate_bus_factor_authors(self, json_entry): 298 | file_authors2changes = {} 299 | lines = json_entry.get('lines') 300 | 301 | #if the file has lines 302 | if lines: 303 | for line in lines: 304 | line_authors2changes = self.calculate_developer_knowledge_line(line, self.DEVELOPER_KNOWLEDGE_CALCULATION) 305 | self.update_file_authors2changes(line_authors2changes, file_authors2changes) 306 | #if the file is an image, a binary files, etc. 307 | else: 308 | file_authors2changes = self.calculate_developer_knowledge_file_change(json_entry, self.DEVELOPER_KNOWLEDGE_CALCULATION) 309 | 310 | bus_factor_authors = self.get_bus_factor_authors(file_authors2changes) 311 | 312 | return bus_factor_authors 313 | 314 | def get_top_three_extensions(self, extensions, file_count): 315 | top3exts = [] 316 | 317 | sorted_keys = self.get_sorted_keys(extensions) 318 | for ext in sorted_keys: 319 | percentage = round((extensions.get(ext)/float(file_count))*100, 2) 320 | top3exts.append({'name': ext, 'percentage': percentage}) 321 | if len(top3exts) > 2: 322 | break 323 | 324 | return top3exts 325 | 326 | def calculate_user_relevance(self, bus_factor_authors, user2relevance): 327 | for bus_factor_user in bus_factor_authors: 328 | if user2relevance.get(bus_factor_user[0]): 329 | relevance = user2relevance.get(bus_factor_user[0]) 330 | user2relevance.update({bus_factor_user[0]: relevance+bus_factor_user[1]}) 331 | else: 332 | user2relevance.update({bus_factor_user[0]: bus_factor_user[1]}) 333 | 334 | def get_user_relevance(self): 335 | user_relevance = [] 336 | repo_json = codecs.open(self.JSON_REPO_PATH, 'r', 'utf-8') 337 | #Each JSON data per line 338 | user2relevance = {} 339 | for json_line in repo_json: 340 | json_entry = json.loads(json_line) 341 | bus_factor_authors = self.calculate_bus_factor_authors(json_entry) 342 | self.calculate_user_relevance(bus_factor_authors, user2relevance) 343 | repo_json.close() 344 | 345 | bus_factor_project = [] 346 | for bf in self.get_bus_factor_authors(user2relevance): 347 | bus_factor_project.append(bf[0]) 348 | #calculate percentage for users involved in bus factors 349 | total_relevance = sum(user2relevance.values()) 350 | sorted_keys = self.get_sorted_keys(user2relevance) 351 | for ur in sorted_keys: 352 | percentage = round((user2relevance.get(ur)/float(total_relevance))*100, 2) 353 | if ur in bus_factor_project: 354 | user_relevance.append({'name': ur, 'knowledge': percentage, 'type': 'user', 'status': 'in bus factor'}) 355 | else: 356 | user_relevance.append({'name': ur, 'knowledge': percentage, 'type': 'user', 'status': 'not in bus factor'}) 357 | 358 | #add to user_relevance the users that are not important for the project 359 | not_important_users = list(self.USERS - set(sorted_keys)) 360 | for niu in not_important_users: 361 | user_relevance.append({'name': niu, 'knowledge': 0, 'type': 'user', 'status': 'not in bus factor'}) 362 | 363 | return user_relevance 364 | 365 | def get_repo_dirs(self): 366 | repo_json = codecs.open(self.JSON_REPO_PATH, 'r', 'utf-8') 367 | dirs = [] 368 | for json_line in repo_json: 369 | json_entry = json.loads(json_line) 370 | if json_entry.get('type') == 'repo': 371 | for d in json_entry.get('dirs'): 372 | dirs.append(d.get('dir')) 373 | repo_json.close() 374 | 375 | return dirs 376 | 377 | def get_repo_exts(self): 378 | repo_json = codecs.open(self.JSON_REPO_PATH, 'r', 'utf-8') 379 | exts = [] 380 | for json_line in repo_json: 381 | json_entry = json.loads(json_line) 382 | if json_entry.get('type') == 'repo': 383 | for d in json_entry.get('exts'): 384 | exts.append(d.get('ext')) 385 | repo_json.close() 386 | 387 | return exts 388 | 389 | def get_repo_branches(self): 390 | repo_json = codecs.open(self.JSON_REPO_PATH, 'r', 'utf-8') 391 | branches = [] 392 | for json_line in repo_json: 393 | json_entry = json.loads(json_line) 394 | if json_entry.get('type') == 'repo': 395 | for d in json_entry.get('branches'): 396 | branches.append(d.get('branch')) 397 | repo_json.close() 398 | 399 | return branches 400 | 401 | def collect_repo_extensions(self, ext): 402 | if self.EXTENSIONS.get(ext): 403 | current_count = self.EXTENSIONS.get(ext) 404 | self.EXTENSIONS.update({ext: current_count+1}) 405 | else: 406 | self.EXTENSIONS.update({ext: 1}) 407 | 408 | def collect_repo_users(self, file_changes): 409 | for fc in file_changes: 410 | committer = fc.get('committer').get('name') 411 | author = fc.get('author').get('name') 412 | 413 | self.USERS.add(committer) 414 | self.USERS.add(author) 415 | 416 | def get_bus_factor_per_file(self): 417 | repo_json = codecs.open(self.JSON_REPO_PATH, 'r', 'utf-8') 418 | #Each JSON data per line 419 | bus_factor_per_file = [] 420 | for json_line in repo_json: 421 | json_entry = json.loads(json_line) 422 | 423 | dirs = json_entry.get('dirs') 424 | ext = json_entry.get('ext') 425 | name = json_entry.get('name') 426 | ref = json_entry.get('ref') 427 | 428 | #collect extensions in repo 429 | self.collect_repo_extensions(ext) 430 | #count files in repo 431 | self.TOTAL_FILES += 1 432 | #collect users in repo 433 | self.collect_repo_users(json_entry.get('file_changes')) 434 | 435 | #get bus factor per file and prepare it to be stored in JSON 436 | bus_factor_entries = [] 437 | for bf in self.calculate_bus_factor_authors(json_entry): 438 | bus_factor_entries.append({'author': bf[0], 'knowledge': bf[1]}) 439 | 440 | bus_factor_per_file.append({'dirs': dirs, 'ext': ext, 'name': name, 'type': 'file', 'ref': ref, 'bus_factor': bus_factor_entries}) 441 | repo_json.close() 442 | 443 | return bus_factor_per_file 444 | 445 | def array2dict_array(self, array): 446 | dict_array = [] 447 | for a in array: 448 | dict_array.append({'author': a[0], 'knowledge': a[1]}) 449 | return dict_array 450 | 451 | def get_bus_factor_per_ref(self): 452 | repo_json = codecs.open(self.JSON_REPO_PATH, 'r', 'utf-8') 453 | #Each JSON data per line 454 | bus_factor = {} 455 | bus_factor_per_ref = [] 456 | for json_line in repo_json: 457 | json_entry = json.loads(json_line) 458 | ref = json_entry.get('ref') 459 | 460 | for bf in self.calculate_bus_factor_authors(json_entry): 461 | author = bf[0] 462 | knowledge = bf[1] 463 | if bus_factor.get(ref): 464 | users_involvement = bus_factor.get(ref) 465 | if users_involvement.get(author): 466 | old_knowledge = users_involvement.get(author) 467 | users_involvement.update({author: old_knowledge+knowledge}) 468 | else: 469 | users_involvement.update({author: knowledge}) 470 | else: 471 | bus_factor.update({ref: {author: knowledge}}) 472 | repo_json.close() 473 | 474 | for bf in bus_factor.keys(): 475 | authors_in_bus_factor = self.get_bus_factor_authors(bus_factor.get(bf)) 476 | bus_factor_per_ref.append({'name': bf, 'type': 'ref', 'bus_factor': self.array2dict_array(authors_in_bus_factor)}) 477 | 478 | return bus_factor_per_ref 479 | 480 | def get_bus_factor_per_extension(self): 481 | repo_json = codecs.open(self.JSON_REPO_PATH, 'r', 'utf-8') 482 | #Each JSON data per line 483 | bus_factor = {} 484 | bus_factor_per_extension = [] 485 | for json_line in repo_json: 486 | json_entry = json.loads(json_line) 487 | ext = json_entry.get('ext').split('.')[-1].lower() 488 | 489 | for bf in self.calculate_bus_factor_authors(json_entry): 490 | author = bf[0] 491 | knowledge = bf[1] 492 | if bus_factor.get(ext): 493 | users_involvement = bus_factor.get(ext) 494 | if users_involvement.get(author): 495 | old_knowledge = users_involvement.get(author) 496 | users_involvement.update({author: old_knowledge+knowledge}) 497 | else: 498 | users_involvement.update({author: knowledge}) 499 | else: 500 | bus_factor.update({ext: {author: knowledge}}) 501 | repo_json.close() 502 | 503 | for bf in bus_factor.keys(): 504 | authors_in_bus_factor = self.get_bus_factor_authors(bus_factor.get(bf)) 505 | bus_factor_per_extension.append({'name': bf, 'type': 'ext', 'bus_factor': self.array2dict_array(authors_in_bus_factor)}) 506 | 507 | return bus_factor_per_extension 508 | 509 | def get_bus_factor_per_directory(self): 510 | repo_json = codecs.open(self.JSON_REPO_PATH, 'r', 'utf-8') 511 | #Each JSON data per line 512 | bus_factor = {} 513 | bus_factor_per_directory = [] 514 | for json_line in repo_json: 515 | json_entry = json.loads(json_line) 516 | ref = json_entry.get('ref') 517 | dirs = json_entry.get('dirs') 518 | if not dirs: 519 | dirs = ['repository_root'] 520 | 521 | for bf in self.calculate_bus_factor_authors(json_entry): 522 | author = bf[0] 523 | knowledge = bf[1] 524 | 525 | for dir in dirs: 526 | if bus_factor.get(dir): 527 | users_involvement = bus_factor.get(dir)[1] 528 | if users_involvement.get(author): 529 | old_knowledge = users_involvement.get(author) 530 | users_involvement.update({author: old_knowledge+knowledge}) 531 | else: 532 | users_involvement.update({author: knowledge}) 533 | else: 534 | bus_factor.update({dir: [ref, {author: knowledge}]}) 535 | repo_json.close() 536 | 537 | for bf in bus_factor.keys(): 538 | ref = bus_factor.get(bf)[0] 539 | authors_in_bus_factor = self.get_bus_factor_authors(bus_factor.get(bf)[1]) 540 | bus_factor_per_directory.append({'name': bf, 'type': 'dir', 'ref': ref, 'bus_factor': self.array2dict_array(authors_in_bus_factor)}) 541 | 542 | return bus_factor_per_directory 543 | 544 | def get_project_info(self): 545 | repo_json = codecs.open(self.JSON_REPO_PATH, 'r', 'utf-8') 546 | json_entry = json.loads(repo_json.readlines()[1]) 547 | if json_entry.get('repo'): 548 | name = json_entry.get('repo') 549 | 550 | return {'name': name} 551 | 552 | def get_extensions_relevance(self): 553 | top3exts = self.get_top_three_extensions(self.EXTENSIONS, self.TOTAL_FILES) 554 | 555 | return top3exts 556 | 557 | def threshold_info(self): 558 | if self.PRIMARY_EXPERT_KNOWLEDGE_PROPORTION == self.DEFAULT: 559 | primary_expert_knowledge = "1ofD" 560 | else: 561 | primary_expert_knowledge = str(self.PRIMARY_EXPERT_KNOWLEDGE_PROPORTION) 562 | 563 | secondary_expert_prop = str(self.SECONDARY_EXPERT_KNOWLEDGE_PROPORTION) 564 | 565 | thresholds = ".thresholds" + ".primary-expert-" + primary_expert_knowledge \ 566 | + ".secondary-expert-proportion-" + secondary_expert_prop 567 | 568 | return thresholds 569 | 570 | def export_bus_factor_information(self): 571 | start_time = datetime.now() 572 | 573 | bus_factor_per_ref = self.get_bus_factor_per_ref() 574 | bus_factor_json = codecs.open(self.JSON_BUS_FACTOR_DIR + "/.references.json", 'w', 'utf-8') 575 | bus_factor_json.write(json.dumps({'references': bus_factor_per_ref}) + "\n") 576 | bus_factor_json.close() 577 | del bus_factor_per_ref 578 | 579 | bus_factor_per_directory = self.get_bus_factor_per_directory() 580 | bus_factor_json = codecs.open(self.JSON_BUS_FACTOR_DIR + "/dirs.json", 'w', 'utf-8') 581 | bus_factor_json.write(json.dumps({'dirs': bus_factor_per_directory}) + "\n") 582 | bus_factor_json.close() 583 | del bus_factor_per_directory 584 | 585 | bus_factor_per_file = self.get_bus_factor_per_file() 586 | bus_factor_json = codecs.open(self.JSON_BUS_FACTOR_DIR + "/files.json", 'w', 'utf-8') 587 | bus_factor_json.write(json.dumps({'files': bus_factor_per_file}) + "\n") 588 | bus_factor_json.close() 589 | del bus_factor_per_file 590 | 591 | bus_factor_per_extension = self.get_bus_factor_per_extension() 592 | bus_factor_json = codecs.open(self.JSON_BUS_FACTOR_DIR + "exts.json", 'w', 'utf-8') 593 | bus_factor_json.write(json.dumps({'exts': bus_factor_per_extension}) + "\n") 594 | bus_factor_json.close() 595 | del bus_factor_per_extension 596 | 597 | user_relevance = self.get_user_relevance() 598 | bus_factor_json = codecs.open(self.JSON_BUS_FACTOR_DIR + "user_relevance.json", 'w', 'utf-8') 599 | bus_factor_json.write(json.dumps({'user_relevance': user_relevance}) + "\n") 600 | bus_factor_json.close() 601 | del user_relevance 602 | 603 | extension_relevance = self.get_extensions_relevance() 604 | bus_factor_json = codecs.open(self.JSON_BUS_FACTOR_DIR + "extension_relevance.json", 'w', 'utf-8') 605 | bus_factor_json.write(json.dumps({'extension_relevance': extension_relevance}) + "\n") 606 | bus_factor_json.close() 607 | del extension_relevance 608 | 609 | project_info = self.get_project_info() 610 | bus_factor_json = codecs.open(self.JSON_BUS_FACTOR_DIR + "project_info.json", 'w', 'utf-8') 611 | bus_factor_json.write(json.dumps({'project_info': project_info}) + "\n") 612 | bus_factor_json.close() 613 | del project_info 614 | 615 | end_time = datetime.now() 616 | 617 | minutes_and_seconds = divmod((end_time-start_time).total_seconds(), 60) 618 | self.logger.info("bus factor metric: process finished after " + str(minutes_and_seconds[0]) 619 | + " minutes and " + str(round(minutes_and_seconds[1], 1)) + " secs") -------------------------------------------------------------------------------- /bus_img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SOM-Research/busfactor/dd83df584dac523b259a5b897724dc78df01037a/bus_img.png -------------------------------------------------------------------------------- /css/bootstrap/bootstrap-theme.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.2.0 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | .btn-default, 8 | .btn-primary, 9 | .btn-success, 10 | .btn-info, 11 | .btn-warning, 12 | .btn-danger { 13 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); 14 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 15 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); 16 | } 17 | .btn-default:active, 18 | .btn-primary:active, 19 | .btn-success:active, 20 | .btn-info:active, 21 | .btn-warning:active, 22 | .btn-danger:active, 23 | .btn-default.active, 24 | .btn-primary.active, 25 | .btn-success.active, 26 | .btn-info.active, 27 | .btn-warning.active, 28 | .btn-danger.active { 29 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 30 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); 31 | } 32 | .btn:active, 33 | .btn.active { 34 | background-image: none; 35 | } 36 | .btn-default { 37 | text-shadow: 0 1px 0 #fff; 38 | background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); 39 | background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); 40 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); 41 | background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); 42 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); 43 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 44 | background-repeat: repeat-x; 45 | border-color: #dbdbdb; 46 | border-color: #ccc; 47 | } 48 | .btn-default:hover, 49 | .btn-default:focus { 50 | background-color: #e0e0e0; 51 | background-position: 0 -15px; 52 | } 53 | .btn-default:active, 54 | .btn-default.active { 55 | background-color: #e0e0e0; 56 | border-color: #dbdbdb; 57 | } 58 | .btn-default:disabled, 59 | .btn-default[disabled] { 60 | background-color: #e0e0e0; 61 | background-image: none; 62 | } 63 | .btn-primary { 64 | background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%); 65 | background-image: -o-linear-gradient(top, #428bca 0%, #2d6ca2 100%); 66 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#2d6ca2)); 67 | background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%); 68 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0); 69 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 70 | background-repeat: repeat-x; 71 | border-color: #2b669a; 72 | } 73 | .btn-primary:hover, 74 | .btn-primary:focus { 75 | background-color: #2d6ca2; 76 | background-position: 0 -15px; 77 | } 78 | .btn-primary:active, 79 | .btn-primary.active { 80 | background-color: #2d6ca2; 81 | border-color: #2b669a; 82 | } 83 | .btn-primary:disabled, 84 | .btn-primary[disabled] { 85 | background-color: #2d6ca2; 86 | background-image: none; 87 | } 88 | .btn-success { 89 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); 90 | background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); 91 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); 92 | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); 93 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); 94 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 95 | background-repeat: repeat-x; 96 | border-color: #3e8f3e; 97 | } 98 | .btn-success:hover, 99 | .btn-success:focus { 100 | background-color: #419641; 101 | background-position: 0 -15px; 102 | } 103 | .btn-success:active, 104 | .btn-success.active { 105 | background-color: #419641; 106 | border-color: #3e8f3e; 107 | } 108 | .btn-success:disabled, 109 | .btn-success[disabled] { 110 | background-color: #419641; 111 | background-image: none; 112 | } 113 | .btn-info { 114 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 115 | background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 116 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); 117 | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); 118 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); 119 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 120 | background-repeat: repeat-x; 121 | border-color: #28a4c9; 122 | } 123 | .btn-info:hover, 124 | .btn-info:focus { 125 | background-color: #2aabd2; 126 | background-position: 0 -15px; 127 | } 128 | .btn-info:active, 129 | .btn-info.active { 130 | background-color: #2aabd2; 131 | border-color: #28a4c9; 132 | } 133 | .btn-info:disabled, 134 | .btn-info[disabled] { 135 | background-color: #2aabd2; 136 | background-image: none; 137 | } 138 | .btn-warning { 139 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 140 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 141 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); 142 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); 143 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); 144 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 145 | background-repeat: repeat-x; 146 | border-color: #e38d13; 147 | } 148 | .btn-warning:hover, 149 | .btn-warning:focus { 150 | background-color: #eb9316; 151 | background-position: 0 -15px; 152 | } 153 | .btn-warning:active, 154 | .btn-warning.active { 155 | background-color: #eb9316; 156 | border-color: #e38d13; 157 | } 158 | .btn-warning:disabled, 159 | .btn-warning[disabled] { 160 | background-color: #eb9316; 161 | background-image: none; 162 | } 163 | .btn-danger { 164 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 165 | background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 166 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); 167 | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); 168 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); 169 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 170 | background-repeat: repeat-x; 171 | border-color: #b92c28; 172 | } 173 | .btn-danger:hover, 174 | .btn-danger:focus { 175 | background-color: #c12e2a; 176 | background-position: 0 -15px; 177 | } 178 | .btn-danger:active, 179 | .btn-danger.active { 180 | background-color: #c12e2a; 181 | border-color: #b92c28; 182 | } 183 | .btn-danger:disabled, 184 | .btn-danger[disabled] { 185 | background-color: #c12e2a; 186 | background-image: none; 187 | } 188 | .thumbnail, 189 | .img-thumbnail { 190 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 191 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 192 | } 193 | .dropdown-menu > li > a:hover, 194 | .dropdown-menu > li > a:focus { 195 | background-color: #e8e8e8; 196 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 197 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 198 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 199 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 200 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 201 | background-repeat: repeat-x; 202 | } 203 | .dropdown-menu > .active > a, 204 | .dropdown-menu > .active > a:hover, 205 | .dropdown-menu > .active > a:focus { 206 | background-color: #357ebd; 207 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); 208 | background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%); 209 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd)); 210 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 211 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 212 | background-repeat: repeat-x; 213 | } 214 | .navbar-default { 215 | background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); 216 | background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); 217 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); 218 | background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); 219 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); 220 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 221 | background-repeat: repeat-x; 222 | border-radius: 4px; 223 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 224 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); 225 | } 226 | .navbar-default .navbar-nav > .active > a { 227 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); 228 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); 229 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f3f3f3)); 230 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%); 231 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0); 232 | background-repeat: repeat-x; 233 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 234 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); 235 | } 236 | .navbar-brand, 237 | .navbar-nav > li > a { 238 | text-shadow: 0 1px 0 rgba(255, 255, 255, .25); 239 | } 240 | .navbar-inverse { 241 | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); 242 | background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); 243 | background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); 244 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); 245 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); 246 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 247 | background-repeat: repeat-x; 248 | } 249 | .navbar-inverse .navbar-nav > .active > a { 250 | background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%); 251 | background-image: -o-linear-gradient(top, #222 0%, #282828 100%); 252 | background-image: -webkit-gradient(linear, left top, left bottom, from(#222), to(#282828)); 253 | background-image: linear-gradient(to bottom, #222 0%, #282828 100%); 254 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0); 255 | background-repeat: repeat-x; 256 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 257 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); 258 | } 259 | .navbar-inverse .navbar-brand, 260 | .navbar-inverse .navbar-nav > li > a { 261 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); 262 | } 263 | .navbar-static-top, 264 | .navbar-fixed-top, 265 | .navbar-fixed-bottom { 266 | border-radius: 0; 267 | } 268 | .alert { 269 | text-shadow: 0 1px 0 rgba(255, 255, 255, .2); 270 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 271 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); 272 | } 273 | .alert-success { 274 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 275 | background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 276 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); 277 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); 278 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); 279 | background-repeat: repeat-x; 280 | border-color: #b2dba1; 281 | } 282 | .alert-info { 283 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 284 | background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 285 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); 286 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); 287 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); 288 | background-repeat: repeat-x; 289 | border-color: #9acfea; 290 | } 291 | .alert-warning { 292 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 293 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 294 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); 295 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); 296 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); 297 | background-repeat: repeat-x; 298 | border-color: #f5e79e; 299 | } 300 | .alert-danger { 301 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 302 | background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 303 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); 304 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); 305 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); 306 | background-repeat: repeat-x; 307 | border-color: #dca7a7; 308 | } 309 | .progress { 310 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 311 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 312 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); 313 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); 314 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 315 | background-repeat: repeat-x; 316 | } 317 | .progress-bar { 318 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%); 319 | background-image: -o-linear-gradient(top, #428bca 0%, #3071a9 100%); 320 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3071a9)); 321 | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); 322 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); 323 | background-repeat: repeat-x; 324 | } 325 | .progress-bar-success { 326 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); 327 | background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); 328 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); 329 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 330 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 331 | background-repeat: repeat-x; 332 | } 333 | .progress-bar-info { 334 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 335 | background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 336 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); 337 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 338 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 339 | background-repeat: repeat-x; 340 | } 341 | .progress-bar-warning { 342 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 343 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 344 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); 345 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 346 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 347 | background-repeat: repeat-x; 348 | } 349 | .progress-bar-danger { 350 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); 351 | background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); 352 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); 353 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 354 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 355 | background-repeat: repeat-x; 356 | } 357 | .progress-bar-striped { 358 | background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 359 | background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 360 | background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); 361 | } 362 | .list-group { 363 | border-radius: 4px; 364 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 365 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075); 366 | } 367 | .list-group-item.active, 368 | .list-group-item.active:hover, 369 | .list-group-item.active:focus { 370 | text-shadow: 0 -1px 0 #3071a9; 371 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%); 372 | background-image: -o-linear-gradient(top, #428bca 0%, #3278b3 100%); 373 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3278b3)); 374 | background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); 375 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); 376 | background-repeat: repeat-x; 377 | border-color: #3278b3; 378 | } 379 | .panel { 380 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 381 | box-shadow: 0 1px 2px rgba(0, 0, 0, .05); 382 | } 383 | .panel-default > .panel-heading { 384 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 385 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 386 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); 387 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 388 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 389 | background-repeat: repeat-x; 390 | } 391 | .panel-primary > .panel-heading { 392 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); 393 | background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%); 394 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd)); 395 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 396 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 397 | background-repeat: repeat-x; 398 | } 399 | .panel-success > .panel-heading { 400 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 401 | background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 402 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); 403 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); 404 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); 405 | background-repeat: repeat-x; 406 | } 407 | .panel-info > .panel-heading { 408 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 409 | background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 410 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); 411 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); 412 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); 413 | background-repeat: repeat-x; 414 | } 415 | .panel-warning > .panel-heading { 416 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 417 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 418 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); 419 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); 420 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); 421 | background-repeat: repeat-x; 422 | } 423 | .panel-danger > .panel-heading { 424 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 425 | background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 426 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); 427 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); 428 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); 429 | background-repeat: repeat-x; 430 | } 431 | .well { 432 | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 433 | background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 434 | background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); 435 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); 436 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); 437 | background-repeat: repeat-x; 438 | border-color: #dcdcdc; 439 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 440 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); 441 | } 442 | /*# sourceMappingURL=bootstrap-theme.css.map */ 443 | -------------------------------------------------------------------------------- /css/bootstrap/bootstrap-theme.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"bootstrap-theme.css","sources":["less/theme.less","less/mixins/vendor-prefixes.less","bootstrap-theme.css","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"AAeA;;;;;;EAME,0CAAA;EC+CA,6FAAA;EACQ,qFAAA;EC5DT;AFiBC;;;;;;;;;;;;EC0CA,0DAAA;EACQ,kDAAA;EC7CT;AFqCC;;EAEE,wBAAA;EEnCH;AFwCD;EG/CI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EA+B2C,2BAAA;EAA2B,oBAAA;EE7BvE;AFAC;;EAEE,2BAAA;EACA,8BAAA;EEEH;AFCC;;EAEE,2BAAA;EACA,uBAAA;EECH;AFEC;;EAEE,2BAAA;EACA,wBAAA;EEAH;AFeD;EGhDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0BD;AFxBC;;EAEE,2BAAA;EACA,8BAAA;EE0BH;AFvBC;;EAEE,2BAAA;EACA,uBAAA;EEyBH;AFtBC;;EAEE,2BAAA;EACA,wBAAA;EEwBH;AFRD;EGjDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EEkDD;AFhDC;;EAEE,2BAAA;EACA,8BAAA;EEkDH;AF/CC;;EAEE,2BAAA;EACA,uBAAA;EEiDH;AF9CC;;EAEE,2BAAA;EACA,wBAAA;EEgDH;AF/BD;EGlDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0ED;AFxEC;;EAEE,2BAAA;EACA,8BAAA;EE0EH;AFvEC;;EAEE,2BAAA;EACA,uBAAA;EEyEH;AFtEC;;EAEE,2BAAA;EACA,wBAAA;EEwEH;AFtDD;EGnDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EEkGD;AFhGC;;EAEE,2BAAA;EACA,8BAAA;EEkGH;AF/FC;;EAEE,2BAAA;EACA,uBAAA;EEiGH;AF9FC;;EAEE,2BAAA;EACA,wBAAA;EEgGH;AF7ED;EGpDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0HD;AFxHC;;EAEE,2BAAA;EACA,8BAAA;EE0HH;AFvHC;;EAEE,2BAAA;EACA,uBAAA;EEyHH;AFtHC;;EAEE,2BAAA;EACA,wBAAA;EEwHH;AF7FD;;ECbE,oDAAA;EACQ,4CAAA;EC8GT;AFvFD;;EGvEI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHsEF,2BAAA;EE6FD;AF3FD;;;EG5EI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH4EF,2BAAA;EEiGD;AFvFD;EG1FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EJ4GA,oBAAA;EC9CA,6FAAA;EACQ,qFAAA;EC4IT;AFlGD;EG1FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,0DAAA;EACQ,kDAAA;ECqJT;AF/FD;;EAEE,gDAAA;EEiGD;AF7FD;EG5GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EFgOD;AFrGD;EG5GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,yDAAA;EACQ,iDAAA;EC0KT;AF9GD;;EAWI,2CAAA;EEuGH;AFlGD;;;EAGE,kBAAA;EEoGD;AF1FD;EACE,+CAAA;EC3FA,4FAAA;EACQ,oFAAA;ECwLT;AFlFD;EGtJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EE8FD;AFzFD;EGvJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EEsGD;AFhGD;EGxJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EE8GD;AFvGD;EGzJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EEsHD;AFtGD;EGlKI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED2QH;AFnGD;EG5KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDkRH;AFzGD;EG7KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDyRH;AF/GD;EG9KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDgSH;AFrHD;EG/KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDuSH;AF3HD;EGhLI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8SH;AF9HD;EGnJI,+MAAA;EACA,0MAAA;EACA,uMAAA;EDoRH;AF1HD;EACE,oBAAA;EC/IA,oDAAA;EACQ,4CAAA;EC4QT;AF3HD;;;EAGE,+BAAA;EGpME,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHkMF,uBAAA;EEiID;AFvHD;ECjKE,mDAAA;EACQ,2CAAA;EC2RT;AFjHD;EG1NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8UH;AFvHD;EG3NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDqVH;AF7HD;EG5NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED4VH;AFnID;EG7NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDmWH;AFzID;EG9NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED0WH;AF/ID;EG/NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDiXH;AF9ID;EGvOI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHqOF,uBAAA;EC1LA,2FAAA;EACQ,mFAAA;EC+UT","sourcesContent":["\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &:disabled,\n &[disabled] {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-bg, 5%); @end-color: darken(@navbar-default-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-bg; @end-color: lighten(@navbar-inverse-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n}\n\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n &::-moz-placeholder { color: @color; // Firefox\n opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n",null,"// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} -------------------------------------------------------------------------------- /css/bootstrap/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.2.0 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default:disabled,.btn-default[disabled]{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-o-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#2d6ca2));background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-primary:disabled,.btn-primary[disabled]{background-color:#2d6ca2;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-success:disabled,.btn-success[disabled]{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-info:disabled,.btn-info[disabled]{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-warning:disabled,.btn-warning[disabled]{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.btn-danger:disabled,.btn-danger[disabled]{background-color:#c12e2a;background-image:none}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f3f3f3));background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:-o-linear-gradient(top,#222 0,#282828 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#222),to(#282828));background-image:linear-gradient(to bottom,#222 0,#282828 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-o-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3071a9));background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-o-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3278b3));background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);background-repeat:repeat-x;border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | 2 | .fileGraph { 3 | margin-top: 10px; 4 | height : 260px; 5 | overflow: scroll; 6 | } 7 | 8 | .factorBox { 9 | margin-top: 30px; 10 | border: 2px solid #c3c3c3; 11 | border-radius: 10px; 12 | padding: 5px 5px 5px 5px; 13 | margin-bottom: 5px 14 | 15 | } 16 | 17 | .factorBox .title { 18 | margin-bottom: 0px; 19 | } 20 | 21 | .factorBox .factor { 22 | font-size: 5em; 23 | margin-top: 0px; 24 | margin-bottom: 0px; 25 | padding-top: 0px; 26 | padding-bottom: 0px; 27 | 28 | } 29 | 30 | .description { 31 | font-size: 1.15em; 32 | display: inline; 33 | } 34 | 35 | .description emph { 36 | font-weight: normal; 37 | } 38 | 39 | 40 | circle { 41 | fill-opacity: .25; 42 | stroke: rgb(31, 119, 180); 43 | stroke-width: 1px; 44 | } 45 | 46 | .leaf circle { 47 | fill: #ff7f0e; 48 | fill-opacity: 1; 49 | } 50 | 51 | text { 52 | font: 10px sans-serif; 53 | } 54 | 55 | .infoTooltip { 56 | position: absolute; 57 | padding: 5px 5px 0px 5px; 58 | margin-bottom: 0px; 59 | background-color: #EEEEEE; 60 | border: solid 1px #777777; 61 | pointer-events: none; 62 | } 63 | 64 | .infoTooltip p { 65 | font-size: 11px; 66 | padding-bottom: 0px; 67 | } 68 | -------------------------------------------------------------------------------- /data/dirs.json: -------------------------------------------------------------------------------- 1 | {"dirs": [{"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/views/devise/mailer/", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/models/", "bus_factor": [{"knowledge": 75.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "config/locales/", "bus_factor": [{"knowledge": 41.51, "author": "Oriol Gual"}, {"knowledge": 32.08, "author": "Gen\u00eds Matutes"}, {"knowledge": 26.42, "author": "Marc Riera"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/views/decidim_hospitalet/surveys/admin/", "bus_factor": [{"knowledge": 55.89, "author": "Oriol Gual"}, {"knowledge": 36.44, "author": "David Morcillo"}]}, {"ref": "origin/master", "type": "dir", "name": "lib/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "config/environments/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "app/views/", "bus_factor": [{"knowledge": 53.33, "author": "Josep Jaume Rey Peroy"}, {"knowledge": 26.67, "author": "David Morcillo"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/lib/decidim_hospitalet/surveys/", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "app/mailers/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "app/views/decidim/devise/", "bus_factor": [{"knowledge": 100.0, "author": "David Morcillo"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/commands/decidim_hospitalet/", "bus_factor": [{"knowledge": 59.43, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/commands/", "bus_factor": [{"knowledge": 52.73, "author": "Oriol Gual"}, {"knowledge": 28.52, "author": "Marc Riera"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/forms/decidim_hospitalet/surveys/", "bus_factor": [{"knowledge": 48.89, "author": "Oriol Gual"}, {"knowledge": 35.87, "author": "Marc Riera"}]}, {"ref": "origin/master", "type": "dir", "name": "public/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/commands/decidim_hospitalet/", "bus_factor": [{"knowledge": 52.73, "author": "Oriol Gual"}, {"knowledge": 28.52, "author": "Marc Riera"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/forms/decidim_hospitalet/", "bus_factor": [{"knowledge": 48.89, "author": "Oriol Gual"}, {"knowledge": 35.87, "author": "Marc Riera"}]}, {"ref": "origin/master", "type": "dir", "name": "test/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/db/", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/", "bus_factor": [{"knowledge": 71.41, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/commands/decidim_hospitalet/surveys/", "bus_factor": [{"knowledge": 59.43, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "app/views/pages/home/", "bus_factor": [{"knowledge": 60.0, "author": "Oriol Gual"}, {"knowledge": 40.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/models/decidim_hospitalet/", "bus_factor": [{"knowledge": 75.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "vendor/assets/stylesheets/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "test/controllers/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/presenters/", "bus_factor": [{"knowledge": 60.0, "author": "Oriol Gual"}, {"knowledge": 40.0, "author": "Aitor Porro"}]}, {"ref": "origin/master", "type": "dir", "name": "app/models/concerns/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/helpers/decidim_hospitalet/surveys/", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/models/decidim_hospitalet/surveys/", "bus_factor": [{"knowledge": 77.78, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "test/models/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "app/views/pages/", "bus_factor": [{"knowledge": 60.0, "author": "Oriol Gual"}, {"knowledge": 40.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "db/", "bus_factor": [{"knowledge": 58.28, "author": "Josep Jaume Rey Peroy"}, {"knowledge": 23.46, "author": "David Morcillo"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/forms/decidim_hospitalet/surveys/admin/", "bus_factor": [{"knowledge": 46.67, "author": "Oriol Gual"}, {"knowledge": 26.67, "author": "Marc Riera"}, {"knowledge": 26.67, "author": "Aitor Porro"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/services/decidim_hospitalet/surveys/", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/helpers/decidim_hospitalet/", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "app/jobs/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/commands/decidim_hospitalet/surveys/admin/", "bus_factor": [{"knowledge": 72.27, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/models/decidim_hospitalet/surveys/", "bus_factor": [{"knowledge": 75.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/views/decidim_hospitalet/surveys/", "bus_factor": [{"knowledge": 53.11, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/views/decidim_hospitalet/", "bus_factor": [{"knowledge": 53.11, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/controllers/decidim_hospitalet/surveys/", "bus_factor": [{"knowledge": 76.6, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/presenters/", "bus_factor": [{"knowledge": 60.0, "author": "Oriol Gual"}, {"knowledge": 40.0, "author": "Aitor Porro"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/controllers/decidim_hospitalet/", "bus_factor": [{"knowledge": 76.6, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/models/decidim_hospitalet/", "bus_factor": [{"knowledge": 77.78, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "test/helpers/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "app/assets/stylesheets/", "bus_factor": [{"knowledge": 60.0, "author": "Josep Jaume Rey Peroy"}, {"knowledge": 40.0, "author": "Gen\u00eds Matutes"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/views/devise/", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "app/assets/javascripts/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "app/views/decidim/devise/registrations/", "bus_factor": [{"knowledge": 100.0, "author": "David Morcillo"}]}, {"ref": "origin/master", "type": "dir", "name": "vendor/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "app/assets/images/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "app/", "bus_factor": [{"knowledge": 86.73, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "app/assets/", "bus_factor": [{"knowledge": 90.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/controllers/", "bus_factor": [{"knowledge": 76.6, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "app/controllers/concerns/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/", "bus_factor": [{"knowledge": 71.19, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/config/locales/", "bus_factor": [{"knowledge": 40.74, "author": "David Morcillo"}, {"knowledge": 37.04, "author": "Oriol Gual"}, {"knowledge": 22.22, "author": "Aitor Porro"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/presenters/decidim_hospitalet/surveys/", "bus_factor": [{"knowledge": 60.0, "author": "Oriol Gual"}, {"knowledge": 40.0, "author": "Aitor Porro"}]}, {"ref": "origin/master", "type": "dir", "name": "vendor/assets/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/assets/images/", "bus_factor": [{"knowledge": 60.0, "author": "Oriol Gual"}, {"knowledge": 40.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/lib/", "bus_factor": [{"knowledge": 81.82, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/views/", "bus_factor": [{"knowledge": 61.23, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "app/assets/javascripts/channels/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "tmp/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/forms/decidim_hospitalet/surveys/admin/", "bus_factor": [{"knowledge": 60.0, "author": "Oriol Gual"}, {"knowledge": 40.0, "author": "Aitor Porro"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/", "bus_factor": [{"knowledge": 67.64, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "config/", "bus_factor": [{"knowledge": 77.57, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/forms/decidim_hospitalet/", "bus_factor": [{"knowledge": 49.02, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "log/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/assets/images/decidim_hospitalet/surveys/", "bus_factor": [{"knowledge": 60.0, "author": "Oriol Gual"}, {"knowledge": 40.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/assets/", "bus_factor": [{"knowledge": 60.0, "author": "Oriol Gual"}, {"knowledge": 40.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/forms/decidim_hospitalet/surveys/", "bus_factor": [{"knowledge": 49.02, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/presenters/decidim_hospitalet/", "bus_factor": [{"knowledge": 60.0, "author": "Oriol Gual"}, {"knowledge": 40.0, "author": "Aitor Porro"}]}, {"ref": "origin/master", "type": "dir", "name": "test/integration/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/services/decidim_hospitalet/", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/shared/", "bus_factor": [{"knowledge": 77.78, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/lib/decidim_hospitalet/surveys/", "bus_factor": [{"knowledge": 77.78, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "bin/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/features/", "bus_factor": [{"knowledge": 79.35, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "app/helpers/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "app/channels/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/lib/", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/commands/decidim_hospitalet/surveys/admin/", "bus_factor": [{"knowledge": 60.6, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "app/channels/application_cable/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "test/mailers/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "lib/tasks/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/views/decidim_hospitalet/surveys/survey_results/", "bus_factor": [{"knowledge": 49.75, "author": "Oriol Gual"}, {"knowledge": 40.36, "author": "Marc Riera"}]}, {"ref": "origin/master", "type": "dir", "name": "app/models/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/presenters/decidim_hospitalet/surveys/", "bus_factor": [{"knowledge": 60.0, "author": "Oriol Gual"}, {"knowledge": 40.0, "author": "Aitor Porro"}]}, {"ref": "origin/master", "type": "dir", "name": "test/fixtures/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/lib/decidim_hospitalet/", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "app/controllers/", "bus_factor": [{"knowledge": 75.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/helpers/decidim_hospitalet/surveys/admin/", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/forms/", "bus_factor": [{"knowledge": 48.89, "author": "Oriol Gual"}, {"knowledge": 35.87, "author": "Marc Riera"}]}, {"ref": "origin/master", "type": "dir", "name": "lib/assets/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/helpers/", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/lib/decidim_hospitalet/", "bus_factor": [{"knowledge": 81.82, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "test/fixtures/files/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/db/migrate/", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/commands/decidim_hospitalet/surveys/", "bus_factor": [{"knowledge": 52.73, "author": "Oriol Gual"}, {"knowledge": 28.52, "author": "Marc Riera"}]}, {"ref": "origin/master", "type": "dir", "name": "app/assets/config/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/commands/", "bus_factor": [{"knowledge": 59.43, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/presenters/decidim_hospitalet/", "bus_factor": [{"knowledge": 60.0, "author": "Oriol Gual"}, {"knowledge": 40.0, "author": "Aitor Porro"}]}, {"ref": "origin/master", "type": "dir", "name": ".github/", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/assets/images/decidim_hospitalet/", "bus_factor": [{"knowledge": 60.0, "author": "Oriol Gual"}, {"knowledge": 40.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/controllers/decidim_hospitalet/surveys/admin/", "bus_factor": [{"knowledge": 75.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/models/", "bus_factor": [{"knowledge": 77.78, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/bin/", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "repository_root", "bus_factor": [{"knowledge": 53.1, "author": "Josep Jaume Rey Peroy"}, {"knowledge": 25.26, "author": "Marc Riera"}]}, {"ref": "origin/master", "type": "dir", "name": "config/initializers/", "bus_factor": [{"knowledge": 86.46, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "app/views/decidim/", "bus_factor": [{"knowledge": 100.0, "author": "David Morcillo"}]}, {"ref": "origin/master", "type": "dir", "name": "vendor/assets/javascripts/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/services/", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/app/views/decidim_hospitalet/surveys/admin/survey_results/", "bus_factor": [{"knowledge": 55.89, "author": "Oriol Gual"}, {"knowledge": 36.44, "author": "David Morcillo"}]}, {"ref": "origin/master", "type": "dir", "name": "app/views/layouts/", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"ref": "origin/master", "type": "dir", "name": "db/migrate/", "bus_factor": [{"knowledge": 58.82, "author": "Josep Jaume Rey Peroy"}, {"knowledge": 23.53, "author": "David Morcillo"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/spec/forms/", "bus_factor": [{"knowledge": 49.02, "author": "Oriol Gual"}]}, {"ref": "origin/master", "type": "dir", "name": "decidim_hospitalet-surveys/config/", "bus_factor": [{"knowledge": 45.24, "author": "Oriol Gual"}, {"knowledge": 28.57, "author": "Aitor Porro"}, {"knowledge": 26.19, "author": "David Morcillo"}]}]} 2 | -------------------------------------------------------------------------------- /data/extension_relevance.json: -------------------------------------------------------------------------------- 1 | {"extension_relevance": [{"percentage": 73.17, "name": "rb"}, {"percentage": 5.92, "name": "keep"}, {"percentage": 5.23, "name": "yml"}]} 2 | -------------------------------------------------------------------------------- /data/exts.json: -------------------------------------------------------------------------------- 1 | {"exts": [{"type": "ext", "name": "procfile", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"type": "ext", "name": "bin/bundle", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"type": "ext", "name": "rb", "bus_factor": [{"knowledge": 53.38, "author": "Josep Jaume Rey Peroy"}, {"knowledge": 19.95, "author": "Oriol Gual"}, {"knowledge": 17.49, "author": "David Morcillo"}]}, {"type": "ext", "name": "ru", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"type": "ext", "name": "lock", "bus_factor": [{"knowledge": 39.52, "author": "Josep Jaume Rey Peroy"}, {"knowledge": 22.45, "author": "David Morcillo"}]}, {"type": "ext", "name": "gemspec", "bus_factor": [{"knowledge": 60.0, "author": "Josep Jaume Rey Peroy"}, {"knowledge": 40.0, "author": "Oriol Gual"}]}, {"type": "ext", "name": "bin/setup", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"type": "ext", "name": "js", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"type": "ext", "name": "bin/update", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"type": "ext", "name": "decidim_hospitalet-surveys/rakefile", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"type": "ext", "name": "keep", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"type": "ext", "name": "png", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"type": "ext", "name": "gitignore", "bus_factor": [{"knowledge": 60.0, "author": "Marc Riera"}, {"knowledge": 40.0, "author": "Aitor Porro"}]}, {"type": "ext", "name": "scss", "bus_factor": [{"knowledge": 100.0, "author": "Gen\u00eds Matutes"}]}, {"type": "ext", "name": "md", "bus_factor": [{"knowledge": 80.0, "author": "Oriol Gual"}]}, {"type": "ext", "name": "txt", "bus_factor": [{"knowledge": 50.0, "author": "Josep Jaume Rey Peroy"}, {"knowledge": 50.0, "author": "Marc Riera"}]}, {"type": "ext", "name": "ico", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"type": "ext", "name": "svg", "bus_factor": [{"knowledge": 60.0, "author": "Oriol Gual"}, {"knowledge": 40.0, "author": "Josep Jaume Rey Peroy"}]}, {"type": "ext", "name": "decidim_hospitalet-surveys/bin/rails", "bus_factor": [{"knowledge": 100.0, "author": "Oriol Gual"}]}, {"type": "ext", "name": "bin/rails", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"type": "ext", "name": "bin/spring", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"type": "ext", "name": "rakefile", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"type": "ext", "name": "json", "bus_factor": [{"knowledge": 100.0, "author": "Marc Riera"}]}, {"type": "ext", "name": "html", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"type": "ext", "name": "bin/rake", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"type": "ext", "name": "erb", "bus_factor": [{"knowledge": 51.12, "author": "Oriol Gual"}]}, {"type": "ext", "name": "ruby-version", "bus_factor": [{"knowledge": 100.0, "author": "David Morcillo"}]}, {"type": "ext", "name": "dockerfile", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}, {"type": "ext", "name": "yml", "bus_factor": [{"knowledge": 44.61, "author": "Josep Jaume Rey Peroy"}, {"knowledge": 16.83, "author": "Oriol Gual"}]}, {"type": "ext", "name": "css", "bus_factor": [{"knowledge": 100.0, "author": "Josep Jaume Rey Peroy"}]}]} 2 | -------------------------------------------------------------------------------- /data/project_info.json: -------------------------------------------------------------------------------- 1 | {"project_info": {"name": "repo_decidim_hospitalet"}} 2 | -------------------------------------------------------------------------------- /data/user_relevance.json: -------------------------------------------------------------------------------- 1 | {"user_relevance": [{"status": "in bus factor", "type": "user", "name": "Josep Jaume Rey Peroy", "knowledge": 55.89}, {"status": "in bus factor", "type": "user", "name": "Oriol Gual", "knowledge": 19.34}, {"status": "not in bus factor", "type": "user", "name": "David Morcillo", "knowledge": 14.46}, {"status": "not in bus factor", "type": "user", "name": "Marc Riera", "knowledge": 6.78}, {"status": "not in bus factor", "type": "user", "name": "Aitor Porro", "knowledge": 1.89}, {"status": "not in bus factor", "type": "user", "name": "Gen\u00eds Matutes", "knowledge": 1.64}, {"status": "not in bus factor", "type": "user", "name": "decidim-bot", "knowledge": 0}, {"status": "not in bus factor", "type": "user", "name": "GitHub", "knowledge": 0}]} 2 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Bus factor 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
18 |

The project

19 |

Summary

20 |

In your project developers contributed actively in files

21 |

(the most important file extensions are ).

22 |

The project will have a hard time if is hit by a bus.

23 |

24 |
25 | 26 |
27 |
28 |

The Bus Factor is:

29 |

30 |
31 | 32 |
33 | 34 |
35 | 36 |
37 |
38 |

User Relevance

39 |
40 | 41 |
42 |
43 | 44 |
45 |
46 |

Branches & Tags (
)

47 |
48 |

Directories (
)

49 |
50 |

Files (
)

51 |
52 |

Extensions (
)

53 |
54 |
55 | 56 |
57 |

Details

58 |
59 |
60 | 61 |
62 | 63 | 64 | 65 |
66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /js/bootstrap/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.2.0 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.2.0",d.prototype.close=function(b){function c(){f.detach().trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",c).emulateTransitionEnd(150):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.2.0",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),d[e](null==f[b]?this.options[b]:f[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b).on("keydown.bs.carousel",a.proxy(this.keydown,this)),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.2.0",c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},c.prototype.keydown=function(a){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.to=function(b){var c=this,d=this.getItemIndex(this.$active=this.$element.find(".item.active"));return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=e[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:g});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,f&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(e)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:g});return a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one("bsTransitionEnd",function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger(m)),f&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(b=!b),e||d.data("bs.collapse",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};c.VERSION="3.2.0",c.DEFAULTS={toggle:!0},c.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},c.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var c=a.Event("show.bs.collapse");if(this.$element.trigger(c),!c.isDefaultPrevented()){var d=this.$parent&&this.$parent.find("> .panel > .in");if(d&&d.length){var e=d.data("bs.collapse");if(e&&e.transitioning)return;b.call(d,"hide"),e||d.data("bs.collapse",null)}var f=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[f](0),this.transitioning=1;var g=function(){this.$element.removeClass("collapsing").addClass("collapse in")[f](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return g.call(this);var h=a.camelCase(["scroll",f].join("-"));this.$element.one("bsTransitionEnd",a.proxy(g,this)).emulateTransitionEnd(350)[f](this.$element[0][h])}}},c.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},c.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var d=a.fn.collapse;a.fn.collapse=b,a.fn.collapse.Constructor=c,a.fn.collapse.noConflict=function(){return a.fn.collapse=d,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(c){var d,e=a(this),f=e.attr("data-target")||c.preventDefault()||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),g=a(f),h=g.data("bs.collapse"),i=h?"toggle":e.data(),j=e.attr("data-parent"),k=j&&a(j);h&&h.transitioning||(k&&k.find('[data-toggle="collapse"][data-parent="'+j+'"]').not(e).addClass("collapsed"),e[g.hasClass("in")?"addClass":"removeClass"]("collapsed")),b.call(g,i)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.2.0",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('