diff --git a/.gitignore b/.gitignore index dc4c6016871d..b749de2d9a22 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,43 @@ +*.py[cod] .idea -*.pyc -*.log +test.py + +# C extensions +*.so + +# Packages +*.egg +*.egg-info +dist +build +eggs +parts +bin +var +sdist +develop-eggs +.installed.cfg +lib +lib64 +__pycache__ + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox +nosetests.xml + +# Translations +*.mo + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject +node_modules +logs +keys +jumpserver.conf +nohup.out diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000000..d7f105139782 --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ +GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {description} + Copyright (C) {year} {fullname} + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/README.md b/README.md index 9ad8cf0e5f1b..eaf65fe33029 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,2 @@ -Jumpserver是什么? ------------------ -Jumpserver是用Python+Django写的一个开源的跳板机(堡垒机)项目,来集中管理服务器的账号、密码和权限。 - -1.1版本更新 ------------------ -更新Log见笔者blog
-http://laoguang.blog.51cto.com/6013350/1576502 - -部署文档 ------------------ -部署文档见笔者blog
-http://laoguang.blog.51cto.com/6013350/1576729 - -功能截图 ------------------ -1. 安装
- ![install](https://github.com/ibuler/static/blob/master/jumpserver1.1/1.%20install.png) -2. 登陆
- ![login](https://github.com/ibuler/static/blob/master/jumpserver1.1/2.login.png) -3. 添加组
-![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/3.addgroup.png) -4. 添加用户
![adduser](https://github.com/ibuler/static/blob/master/jumpserver1.1/5.adduser.png) -5. 添加主机
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/9.addhost.png) -6. 添加权限
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/11.addperm.png) -7. 查看权限
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/13.showperm.png) -8. 下载私钥
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/16.downkey.png) -9. 登陆shell
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/17.loginshell.png) -10. 显示有权限的主机
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/18.p.png) -11. 批量执行命令
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/19.e.png) -12. 登陆有权限的主机
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/20.%20loginserver.png) -13. 查看sudo
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/22.showsudo.png) -14. 修改sudo
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/25.addsudohost.png) -15. 查看实时监控
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/29.monitor1ok.png) -16. 结束会话
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/28.%20killsession.png) -17. 查看统计日志
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/30.viewlog2.png) -18. 修改密码
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/34.modpass.png) -19. 下载文件
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/32.downfile.png) -20. 上传文件
![addgroup](https://github.com/ibuler/static/blob/master/jumpserver1.1/30.upfile.png) +# jumpserver +# diff --git a/connect.py b/connect.py new file mode 100644 index 000000000000..8a4949662c86 --- /dev/null +++ b/connect.py @@ -0,0 +1,387 @@ +# coding: utf-8 + +import sys + +reload(sys) +sys.setdefaultencoding('utf8') + +import socket +import os +import re +import ast +import select +import time +import paramiko +import struct +import fcntl +import signal +import textwrap +import django +import getpass +import fnmatch +import readline +from multiprocessing import Pool + + +os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings' +django.setup() +from juser.models import User + +from jlog.models import Log +from jumpserver.api import * + +try: + import termios + import tty +except ImportError: + print '\033[1;31mOnly postfix supported.\033[0m' + time.sleep(3) + sys.exit() + +CONF.read(os.path.join(BASE_DIR, 'jumpserver.conf')) +LOG_DIR = os.path.join(BASE_DIR, 'logs') +SSH_KEY_DIR = os.path.join(BASE_DIR, 'keys') +SERVER_KEY_DIR = os.path.join(SSH_KEY_DIR, 'server') +LOGIN_NAME = getpass.getuser() + + +def color_print(msg, color='blue'): + """Print colorful string.""" + color_msg = {'blue': '\033[1;36m%s\033[0m', + 'green': '\033[1;32m%s\033[0m', + 'red': '\033[1;31m%s\033[0m'} + + print color_msg.get(color, 'blue') % msg + + +def color_print_exit(msg, color='red'): + """Print colorful string and exit.""" + color_print(msg, color=color) + time.sleep(2) + sys.exit() + + +def get_win_size(): + """This function use to get the size of the windows!""" + if 'TIOCGWINSZ' in dir(termios): + TIOCGWINSZ = termios.TIOCGWINSZ + else: + TIOCGWINSZ = 1074295912L # Assume + s = struct.pack('HHHH', 0, 0, 0, 0) + x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s) + return struct.unpack('HHHH', x)[0:2] + + +def set_win_size(sig, data): + """This function use to set the window size of the terminal!""" + try: + win_size = get_win_size() + channel.resize_pty(height=win_size[0], width=win_size[1]) + except: + pass + + +def log_record(username, host): + """Logging user command and output.""" + connect_log_dir = os.path.join(LOG_DIR, 'connect') + timestamp_start = int(time.time()) + today = time.strftime('%Y%m%d', time.localtime(timestamp_start)) + time_now = time.strftime('%H%M%S', time.localtime(timestamp_start)) + today_connect_log_dir = os.path.join(connect_log_dir, today) + log_filename = '%s_%s_%s.log' % (username, host, time_now) + log_file_path = os.path.join(today_connect_log_dir, log_filename) + dept_name = User.objects.get(username=username).dept.name + pid = os.getpid() + ip_list = [] + remote_ip = os.popen("who |grep `ps aux |gawk '{if ($2==%s) print $1}'` |gawk '{print $5}'|tr -d '()'" % pid).readlines() + for ip in remote_ip: + ip_list.append(ip.strip('\n')) + ip_list = ','.join(list(set(ip_list))) + + if not os.path.isdir(today_connect_log_dir): + try: + os.makedirs(today_connect_log_dir) + os.chmod(today_connect_log_dir, 0777) + except OSError: + raise ServerError('Create %s failed, Please modify %s permission.' % (today_connect_log_dir, connect_log_dir)) + + try: + log_file = open(log_file_path, 'a') + except IOError: + raise ServerError('Create logfile failed, Please modify %s permission.' % today_connect_log_dir) + + log = Log(user=username, host=host, remote_ip=ip_list, dept_name=dept_name, + log_path=log_file_path, start_time=datetime.datetime.now(), pid=pid) + log_file.write('Starttime is %s\n' % datetime.datetime.now()) + log.save() + return log_file, log + + +def posix_shell(chan, username, host): + """ + Use paramiko channel connect server interactive. + """ + log_file, log = log_record(username, host) + old_tty = termios.tcgetattr(sys.stdin) + try: + tty.setraw(sys.stdin.fileno()) + tty.setcbreak(sys.stdin.fileno()) + chan.settimeout(0.0) + + while True: + try: + r, w, e = select.select([chan, sys.stdin], [], []) + except: + pass + + if chan in r: + try: + x = chan.recv(1024) + if len(x) == 0: + break + sys.stdout.write(x) + sys.stdout.flush() + log_file.write(x) + log_file.flush() + except socket.timeout: + pass + + if sys.stdin in r: + x = os.read(sys.stdin.fileno(), 1) + if len(x) == 0: + break + chan.send(x) + + finally: + termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty) + log_file.write('Endtime is %s' % datetime.datetime.now()) + log_file.close() + log.is_finished = True + log.log_finished = False + log.end_time = datetime.datetime.now() + log.save() + print_prompt() + + +def get_user_hostgroup(username): + """Get the hostgroups of under the user control.""" + groups_attr = {} + group_all = user_perm_group_api(username) + for group in group_all: + groups_attr[group.name] = [group.id, group.comment] + return groups_attr + + +def get_user_hostgroup_host(username, gid): + """Get the hostgroup hosts of under the user control.""" + hosts_attr = {} + user = User.objects.get(username=username) + hosts = user_perm_group_hosts_api(gid) + for host in hosts: + alias = AssetAlias.objects.filter(user=user, host=host) + if alias and alias[0].alias != '': + hosts_attr[host.ip] = [host.id, host.ip, alias[0].alias] + else: + hosts_attr[host.ip] = [host.id, host.ip, host.comment] + return hosts_attr + + +def verify_connect(username, part_ip): + ip_matched = [] + try: + hosts_attr = get_user_host(username) + hosts = hosts_attr.values() + except ServerError, e: + color_print(e, 'red') + return False + for ip_info in hosts: + for info in ip_info[1:]: + if part_ip in info: + ip_matched.append(ip_info[1]) + if len(ip_matched) > 1: + for ip in ip_matched: + print '%s -- %s' % (ip, hosts_attr[ip][2]) + elif len(ip_matched) < 1: + color_print('No Permission or No host.', 'red') + else: + username, password, host, port = get_connect_item(username, ip_matched[0]) + connect(username, password, host, port, LOGIN_NAME) + + +def print_prompt(): + msg = """\033[1;32m### Welcome Use JumpServer To Login. ### \033[0m + 1) Type \033[32mIP ADDRESS\033[0m To Login. + 2) Type \033[32mP/p\033[0m To Print The Servers You Available. + 3) Type \033[32mG/g\033[0m To Print The Server Groups You Available. + 4) Type \033[32mG/g(1-N)\033[0m To Print The Server Group Hosts You Available. + 5) Type \033[32mE/e\033[0m To Execute Command On Several Servers. + 6) Type \033[32mQ/q\033[0m To Quit. + """ + print textwrap.dedent(msg) + + +def print_user_host(username): + try: + hosts_attr = get_user_host(username) + except ServerError, e: + color_print(e, 'red') + return + hosts = hosts_attr.keys() + hosts.sort() + for ip in hosts: + print '%-15s -- %s' % (ip, hosts_attr[ip][2]) + print '' + + +def print_user_hostgroup(username): + group_attr = get_user_hostgroup(username) + groups = group_attr.keys() + for g in groups: + print "[%3s] %s -- %s" % (group_attr[g][0], g, group_attr[g][1]) + + +def print_user_hostgroup_host(username, gid): + pattern = re.compile(r'\d+') + match = pattern.match(gid) + if match: + hosts_attr = get_user_hostgroup_host(username, gid) + hosts = hosts_attr.keys() + hosts.sort() + for ip in hosts: + print '%-15s -- %s' % (ip, hosts_attr[ip][2]) + else: + color_print('No such group id, Please check it.', 'red') + + +def connect(username, password, host, port, login_name): + """ + Connect server. + """ + ps1 = "PS1='[\u@%s \W]\$ '\n" % host + login_msg = "clear;echo -e '\\033[32mLogin %s done. Enjoy it.\\033[0m'\n" % host + + # Make a ssh connection + ssh = paramiko.SSHClient() + ssh.load_system_host_keys() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + try: + ssh.connect(host, port=port, username=username, password=password, compress=True) + except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException: + raise ServerError('Authentication Error.') + except socket.error: + raise ServerError('Connect SSH Socket Port Error, Please Correct it.') + + # Make a channel and set windows size + global channel + win_size = get_win_size() + channel = ssh.invoke_shell(height=win_size[0], width=win_size[1]) + try: + signal.signal(signal.SIGWINCH, set_win_size) + except: + pass + + # Set PS1 and msg it + channel.send(ps1) + channel.send(login_msg) + + # Make ssh interactive tunnel + posix_shell(channel, login_name, host) + + # Shutdown channel socket + channel.close() + ssh.close() + + +def remote_exec_cmd(ip, port, username, password, cmd): + try: + time.sleep(5) + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect(ip, port, username, password, timeout=5) + stdin, stdout, stderr = ssh.exec_command("bash -l -c '%s'" % cmd) + out = stdout.readlines() + err = stderr.readlines() + color_print('%s:' % ip, 'blue') + for i in out: + color_print(" " * 4 + i.strip(), 'green') + for j in err: + color_print(" " * 4 + j.strip(), 'red') + ssh.close() + except Exception as e: + color_print(ip + ':', 'blue') + color_print(str(e), 'red') + + +def multi_remote_exec_cmd(hosts, username, cmd): + pool = Pool(processes=5) + for host in hosts: + username, password, ip, port = get_connect_item(username, host) + pool.apply_async(remote_exec_cmd, (ip, port, username, password, cmd)) + pool.close() + pool.join() + + +def exec_cmd_servers(username): + hosts = [] + color_print("Input the Host IP(s),Separated by Commas, q/Q to Quit.\n \ + You can choose in the following IP(s), Use Linux / Unix glob.", 'green') + print_user_host(LOGIN_NAME) + while True: + inputs = raw_input('\033[1;32mip(s)>: \033[0m') + if inputs in ['q', 'Q']: + break + get_hosts = get_user_host(username).keys() + for host in get_hosts: + if fnmatch.fnmatch(host, inputs): + hosts.append(host.strip()) + if len(hosts) == 0: + color_print("Check again, Not matched any ip!", 'red') + continue + else: + print "You matched ip: %s" % hosts + color_print("Input the Command , The command will be Execute on servers, q/Q to quit.", 'green') + while True: + cmd = raw_input('\033[1;32mCmd(s): \033[0m') + if cmd in ['q', 'Q']: + break + exec_log_dir = os.path.join(LOG_DIR, 'exec_cmds') + if not os.path.isdir(exec_log_dir): + os.mkdir(exec_log_dir) + os.chmod(exec_log_dir, 0777) + filename = "%s/%s.log" % (exec_log_dir, time.strftime('%Y%m%d')) + f = open(filename, 'a') + f.write("DateTime: %s User: %s Host: %s Cmds: %s\n" % + (time.strftime('%Y/%m/%d %H:%M:%S'), username, hosts, cmd)) + multi_remote_exec_cmd(hosts, username, cmd) + + +if __name__ == '__main__': + print_prompt() + try: + while True: + try: + option = raw_input("\033[1;32mOpt or IP>:\033[0m ") + except EOFError: + print + continue + if option in ['P', 'p']: + print_user_host(LOGIN_NAME) + continue + elif option in ['G', 'g']: + print_user_hostgroup(LOGIN_NAME) + continue + elif option.startswith('g') or option.startswith('G'): + gid = option[1:].strip() + print_user_hostgroup_host(LOGIN_NAME, gid) + continue + elif option in ['E', 'e']: + exec_cmd_servers(LOGIN_NAME) + elif option in ['Q', 'q', 'exit']: + sys.exit() + else: + try: + verify_connect(LOGIN_NAME, option) + except ServerError, e: + color_print(e, 'red') + except IndexError: + pass diff --git a/docs/AddUserAsset.py b/docs/AddUserAsset.py new file mode 100644 index 000000000000..ec918f56b38b --- /dev/null +++ b/docs/AddUserAsset.py @@ -0,0 +1,141 @@ +#coding:utf-8 +import django +import os +import sys +import random +import datetime + +sys.path.append('../') +os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings' +django.setup() + + +from juser.views import db_add_user, md5_crypt, CRYPTOR, db_add_group +from jasset.models import Asset, IDC, BisGroup +from juser.models import UserGroup, DEPT, User +from jperm.models import CmdGroup +from jlog.models import Log + + +def install(): + IDC.objects.create(name='ALL', comment='ALL') + IDC.objects.create(name='默认', comment='默认') + DEPT.objects.create(name="默认", comment="默认部门") + DEPT.objects.create(name="超管部", comment="超级管理员部门") + dept = DEPT.objects.get(name='超管部') + dept2 = DEPT.objects.get(name='默认') + UserGroup.objects.create(name='ALL', dept=dept, comment='ALL') + UserGroup.objects.create(name='默认', dept=dept, comment='默认') + + BisGroup.objects.create(name='ALL', dept=dept, comment='ALL') + BisGroup.objects.create(name='默认', dept=dept, comment='默认') + + User(id=5000, username="admin", password=md5_crypt('admin'), + name='admin', email='admin@jumpserver.org', role='SU', is_active=True, dept=dept).save() + User(id=5001, username="group_admin", password=md5_crypt('group_admin'), + name='group_admin', email='group_admin@jumpserver.org', role='DA', is_active=True, dept=dept2).save() + + +def test_add_idc(): + for i in range(1, 20): + name = 'IDC' + str(i) + IDC.objects.create(name=name, comment='') + print 'Add: %s' % name + + +def test_add_dept(): + for i in range(1, 100): + name = 'DEPT' + str(i) + print "Add: %s" % name + DEPT.objects.create(name=name, comment=name) + + +def test_add_group(): + dept_all = DEPT.objects.all() + for i in range(1, 100): + name = 'UserGroup' + str(i) + UserGroup.objects.create(name=name, dept=random.choice(dept_all), comment=name) + print 'Add: %s' % name + + +def test_add_cmd_group(): + for i in range(1, 20): + name = 'CMD' + str(i) + cmd = '/sbin/ping%s, /sbin/ifconfig/' % str(i) + CmdGroup.objects.create(name=name, cmd=cmd, comment=name) + print 'Add: %s' % name + + +def test_add_user(): + for i in range(1, 500): + username = "test" + str(i) + dept_all = DEPT.objects.all() + group_all = UserGroup.objects.all() + group_all_id = [group.id for group in group_all] + db_add_user(username=username, + password=md5_crypt(username), + dept=random.choice(dept_all), + name=username, email='%s@jumpserver.org' % username, + groups=[random.choice(group_all_id) for i in range(1, 4)], role='CU', + ssh_key_pwd=CRYPTOR.encrypt(username), + ldap_pwd=CRYPTOR.encrypt(username), + is_active=True, + date_joined=datetime.datetime.now()) + print "Add: %s" % username + + +def test_add_asset_group(): + dept = DEPT.objects.get(name='默认') + for i in range(1, 20): + name = 'AssetGroup' + str(i) + group = BisGroup(name=name, dept=dept, comment=name) + group.save() + print 'Add: %s' % name + + +def test_add_asset(): + idc_all = IDC.objects.all() + test_idc = random.choice(idc_all) + bis_group_all = BisGroup.objects.all() + dept_all = DEPT.objects.all() + for i in range(1, 500): + ip = '192.168.1.' + str(i) + asset = Asset(ip=ip, port=22, login_type='L', idc=test_idc, is_active=True, comment='test') + asset.save() + asset.bis_group = [random.choice(bis_group_all) for i in range(2)] + asset.dept = [random.choice(dept_all) for i in range(2)] + print "Add: %s" % ip + + +def test_add_log(): + li_date = [] + today = datetime.date.today() + oneday = datetime.timedelta(days=1) + for i in range(0, 7): + today = today-oneday + li_date.append(today) + user_list = ['马云', '马化腾', '丁磊', '周鸿祎', '雷军', '柳传志', '陈天桥', '李彦宏', '李开复', '罗永浩'] + for i in range(1, 1000): + user = random.choice(user_list) + ip = random.randint(1, 20) + start_time = random.choice(li_date) + end_time = datetime.datetime.now() + log_path = '/var/log/jumpserver/test.log' + host = '192.168.1.' + str(ip) + Log.objects.create(user=user, host=host, remote_ip='8.8.8.8', dept_name='运维部', log_path=log_path, pid=168, start_time=start_time, + is_finished=1, log_finished=1, end_time=end_time) + + +if __name__ == '__main__': + #install() + test_add_dept() + test_add_group() + test_add_user() + test_add_idc() + test_add_asset_group() + test_add_asset() + test_add_log() + + + + diff --git a/webroot/__init__.py b/docs/__init__.py similarity index 100% rename from webroot/__init__.py rename to docs/__init__.py diff --git a/docs/developer_doc.txt b/docs/developer_doc.txt new file mode 100644 index 000000000000..d24cacdcda1b --- /dev/null +++ b/docs/developer_doc.txt @@ -0,0 +1,36 @@ +# coding: utf8 + +Jumpserver开发者文档 + +开发规范: + 1. 遵守PE8规范 1) 命名规范 2) 导入模块规范 3) 空行规范 4) 长度规范 + 2. 缩进统一4个空格 + 3. 变量命名明了易懂多个单词下划线隔开 + 4. 注释到位 + + +框架说明: + 1. 项目名称 Jumpserver + 2. APP: + juser 用户管理 + jasset 资产管理(设备管理) + jpermission 授权管理 + jlog 日志管理 + 3. connect.py 用户登录入口程序 + 4. logs 日志保存目录 + 5. jumpserver.conf 配置文件 + 6. docs 文档目录 + 7. static 静态文件目录 + 8. templates 模板目录 + + +connect.py逻辑说明: + 用户登录系统,运行该脚本,p调用get_user_host函数查看有权限的服务器ip + 输入部分IP,verify_connect匹配该部分ip,如果是匹配到多个,就显示ip + 匹配到0了就显示没有权限或者主机, + 匹配到1个则继续 + 查询该服务器是否支持ldap 如果是,获得ldap用户密码登陆 + 如果否,查询授权表,查看该服务器授权的角色,并返回对应账号密码,登陆 + connect函数是登陆函数,采用paramiko 使用channel登陆,posix_shell 来完成交互,并记录日志 + signal模块来完成窗口改变导致的tty大小随之改变 + PyCrypt是对称加密类 \ No newline at end of file diff --git a/docs/install.py b/docs/install.py new file mode 100644 index 000000000000..76a7da52239f --- /dev/null +++ b/docs/install.py @@ -0,0 +1,135 @@ +#coding:utf-8 +import django +import os +import sys +import random +import datetime + +sys.path.append('../') +os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings' +django.setup() + + +from juser.views import db_add_user, md5_crypt, CRYPTOR, db_add_group +from jasset.models import Asset, IDC, BisGroup +from juser.models import UserGroup, DEPT, User +from jasset.views import jasset_group_add +from jperm.models import CmdGroup +from jlog.models import Log + + +def install(): + IDC.objects.create(name='ALL', comment='ALL') + IDC.objects.create(name='默认', comment='默认') + DEPT.objects.create(name="默认", comment="默认部门") + DEPT.objects.create(name="超管部", comment="超级管理员部门") + dept = DEPT.objects.get(name='超管部') + dept2 = DEPT.objects.get(name='默认') + UserGroup.objects.create(name='ALL', dept=dept, comment='ALL') + UserGroup.objects.create(name='默认', dept=dept, comment='默认') + + BisGroup.objects.create(name='ALL', dept=dept, comment='ALL') + BisGroup.objects.create(name='默认', dept=dept, comment='默认') + + User(id=5000, username="admin", password=md5_crypt('admin'), + name='admin', email='admin@jumpserver.org', role='SU', is_active=True, dept=dept).save() + User(id=5001, username="group_admin", password=md5_crypt('group_admin'), + name='group_admin', email='group_admin@jumpserver.org', role='DA', is_active=True, dept=dept2).save() + + +def test_add_idc(): + for i in range(1, 20): + name = 'IDC' + str(i) + IDC.objects.create(name=name, comment='') + print 'Add: %s' % name + + +def test_add_dept(): + for i in range(1, 100): + name = 'DEPT' + str(i) + print "Add: %s" % name + DEPT.objects.create(name=name, comment=name) + + +def test_add_group(): + dept_all = DEPT.objects.all() + for i in range(1, 100): + name = 'UserGroup' + str(i) + UserGroup.objects.create(name=name, dept=random.choice(dept_all), comment=name) + print 'Add: %s' % name + + +def test_add_cmd_group(): + for i in range(1, 20): + name = 'CMD' + str(i) + cmd = '/sbin/ping%s, /sbin/ifconfig/' % str(i) + CmdGroup.objects.create(name=name, cmd=cmd, comment=name) + print 'Add: %s' % name + + +def test_add_user(): + for i in range(1, 500): + username = "test" + str(i) + dept_all = DEPT.objects.all() + group_all = UserGroup.objects.all() + group_all_id = [group.id for group in group_all] + db_add_user(username=username, + password=md5_crypt(username), + dept=random.choice(dept_all), + name=username, email='%s@jumpserver.org' % username, + groups=[random.choice(group_all_id) for i in range(1, 4)], role='CU', + ssh_key_pwd=CRYPTOR.encrypt(username), + ldap_pwd=CRYPTOR.encrypt(username), + is_active=True, + date_joined=datetime.datetime.now()) + print "Add: %s" % username + + +def test_add_asset_group(): + dept = DEPT.objects.get(name='默认') + for i in range(1, 20): + name = 'AssetGroup' + str(i) + group = BisGroup(name=name, dept=dept, comment=name) + group.save() + print 'Add: %s' % name + + +def test_add_asset(): + idc_all = IDC.objects.all() + test_idc = random.choice(idc_all) + bis_group_all = BisGroup.objects.all() + dept_all = DEPT.objects.all() + for i in range(1, 500): + ip = '192.168.1.' + str(i) + asset = Asset(ip=ip, port=22, login_type='L', idc=test_idc, is_active=True, comment='test') + asset.save() + asset.bis_group = [random.choice(bis_group_all) for i in range(2)] + asset.dept = [random.choice(dept_all) for i in range(2)] + print "Add: %s" % ip + + +def test_add_log(): + li_date = [] + today = datetime.date.today() + oneday = datetime.timedelta(days=1) + for i in range(0, 7): + today = today-oneday + li_date.append(today) + user_list = ['马云', '马化腾', '丁磊', '周鸿祎', '雷军', '柳传志', '陈天桥', '李彦宏', '李开复', '罗永浩'] + for i in range(1, 1000): + user = random.choice(user_list) + ip = random.randint(1, 20) + start_time = random.choice(li_date) + end_time = datetime.datetime.now() + log_path = '/var/log/jumpserver/test.log' + host = '192.168.1.' + str(ip) + Log.objects.create(user=user, host=host, log_path=log_path, pid=168, start_time=start_time, + is_finished=1, log_finished=1, end_time=end_time) + + +if __name__ == '__main__': + install() + + + + diff --git a/scripts/requirements.txt b/docs/require.txt similarity index 81% rename from scripts/requirements.txt rename to docs/require.txt index 766faa1c96b3..85d351fe8b3e 100644 --- a/scripts/requirements.txt +++ b/docs/require.txt @@ -1,9 +1,10 @@ -pexpect==3.3 -sphinx-me==0.3 -django==1.7.1 -python-ldap==2.4.18 -paramiko==1.15.1 -pycrypto==2.6.1 -ecdsa>=0.11 -MySQL-python==1.2.5 -readline +pexpect==3.3 +sphinx-me==0.3 +django==1.6 +python-ldap==2.4.18 +paramiko==1.15.1 +pycrypto==2.6.1 +ecdsa>=0.11 +MySQL-python==1.2.5 +readline +django-uuidfield \ No newline at end of file diff --git a/webroot/AutoSa/Assets/__init__.py b/jasset/__init__.py similarity index 100% rename from webroot/AutoSa/Assets/__init__.py rename to jasset/__init__.py diff --git a/webroot/AutoSa/Assets/admin.py b/jasset/admin.py similarity index 100% rename from webroot/AutoSa/Assets/admin.py rename to jasset/admin.py diff --git a/jasset/models.py b/jasset/models.py new file mode 100644 index 000000000000..d7821fd933b4 --- /dev/null +++ b/jasset/models.py @@ -0,0 +1,54 @@ +import datetime +from django.db import models +from juser.models import User, UserGroup, DEPT + + +class IDC(models.Model): + name = models.CharField(max_length=40, unique=True) + comment = models.CharField(max_length=80, blank=True, null=True) + + def __unicode__(self): + return self.name + + +class BisGroup(models.Model): + GROUP_TYPE = ( + ('P', 'PRIVATE'), + ('A', 'ASSET'), + ) + name = models.CharField(max_length=80, unique=True) + dept = models.ForeignKey(DEPT) + comment = models.CharField(max_length=160, blank=True, null=True) + + def __unicode__(self): + return self.name + + +class Asset(models.Model): + LOGIN_TYPE_CHOICES = ( + ('L', 'LDAP'), + ('M', 'MAP'), + ) + ip = models.IPAddressField(unique=True) + port = models.SmallIntegerField(max_length=5) + idc = models.ForeignKey(IDC) + bis_group = models.ManyToManyField(BisGroup) + dept = models.ManyToManyField(DEPT) + login_type = models.CharField(max_length=1, choices=LOGIN_TYPE_CHOICES, default='L') + username = models.CharField(max_length=20, blank=True, null=True) + password = models.CharField(max_length=80, blank=True, null=True) + date_added = models.DateTimeField(auto_now=True, default=datetime.datetime.now(), null=True) + is_active = models.BooleanField(default=True) + comment = models.CharField(max_length=100, blank=True, null=True) + + def __unicode__(self): + return self.ip + + +class AssetAlias(models.Model): + user = models.ForeignKey(User) + host = models.ForeignKey(Asset) + alias = models.CharField(max_length=100, blank=True, null=True) + + def __unicode__(self): + return self.comment \ No newline at end of file diff --git a/webroot/AutoSa/Assets/tests.py b/jasset/tests.py similarity index 100% rename from webroot/AutoSa/Assets/tests.py rename to jasset/tests.py diff --git a/jasset/urls.py b/jasset/urls.py new file mode 100644 index 000000000000..da52529b649e --- /dev/null +++ b/jasset/urls.py @@ -0,0 +1,28 @@ +# coding:utf-8 +from django.conf.urls import patterns, include, url +from jasset.views import * + +urlpatterns = patterns('', + url(r'^host_add/$', host_add), + url(r"^host_add_multi/$", host_add_batch), + url(r'^host_list/$', host_list), + url(r'^search/$', host_search), + url(r"^host_detail/$", host_detail), + url(r"^dept_host_ajax/$", dept_host_ajax), + url(r"^show_all_ajax/$", show_all_ajax), + url(r'^idc_add/$', idc_add), + url(r'^idc_list/$', idc_list), + url(r'^idc_edit/$', idc_edit), + url(r'^idc_detail/$', idc_detail), + url(r'^idc_del/$', idc_del), + url(r'^group_add/$', group_add), + url(r'^group_edit/$', group_edit), + url(r'^group_list/$', group_list), + url(r'^group_detail/$', group_detail), + url(r'^group_del_host/$', group_del_host), + url(r'^group_del/$', group_del), + url(r'^host_del/(\w+)/$', host_del), + url(r'^host_edit/$', view_splitter, {'su': host_edit, 'adm': host_edit_adm}), + url(r'^host_edit/batch/$', host_edit_batch), + url(r'^host_edit_common/batch/$', host_edit_common_batch), +) \ No newline at end of file diff --git a/jasset/views.py b/jasset/views.py new file mode 100644 index 000000000000..a62aaca00f5b --- /dev/null +++ b/jasset/views.py @@ -0,0 +1,927 @@ +# coding:utf-8 + +import ast + +from django.db.models import Q +from django.template import RequestContext +from jperm.models import Perm +from jumpserver.api import * + +cryptor = PyCrypt(KEY) + + +class RaiseError(Exception): + pass + + +def my_render(template, data, request): + return render_to_response(template, data, context_instance=RequestContext(request)) + + +def get_host_groups(groups): + """ 获取主机所属的组类 """ + ret = [] + for group_id in groups: + group = BisGroup.objects.filter(id=group_id) + if group: + group = group[0] + ret.append(group) + return ret + + +def get_host_depts(depts): + """ 获取主机所属的部门类 """ + ret = [] + for dept_id in depts: + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept = dept[0] + ret.append(dept) + return ret + + +def db_host_insert(host_info, username='', password=''): + """ 添加主机时数据库操作函数 """ + ip, port, idc, jtype, group, dept, active, comment = host_info + idc = IDC.objects.filter(id=idc) + if idc: + idc = idc[0] + if jtype == 'M': + password = cryptor.encrypt(password) + a = Asset(ip=ip, port=port, + login_type=jtype, idc=idc, + is_active=int(active), + comment=comment, + username=username, + password=password) + else: + a = Asset(ip=ip, port=port, + login_type=jtype, idc=idc, + is_active=int(active), + comment=comment) + a.save() + + all_group = BisGroup.objects.get(name='ALL') + groups = get_host_groups(group) + groups.append(all_group) + + depts = get_host_depts(dept) + + a.bis_group = groups + a.dept = depts + a.save() + + +def db_host_update(host_info, username='', password=''): + """ 修改主机时数据库操作函数 """ + ip, port, idc, jtype, group, dept, active, comment, host = host_info + idc = IDC.objects.filter(id=idc) + if idc: + idc = idc[0] + groups = get_host_groups(group) + depts = get_host_depts(dept) + host.ip = ip + host.port = port + host.login_type = jtype + host.idc = idc + host.is_active = int(active) + host.comment = comment + + if jtype == 'M': + if password != host.password: + password = cryptor.encrypt(password) + host.password = password + host.username = username + host.password = password + host.save() + host.bis_group = groups + host.dept = depts + host.save() + + +def batch_host_edit(host_info, j_user='', j_password=''): + """ 批量修改主机函数 """ + j_id, j_ip, j_idc, j_port, j_type, j_group, j_dept, j_active, j_comment = host_info + groups, depts = [], [] + is_active = {u'是': '1', u'否': '2'} + login_types = {'LDAP': 'L', 'MAP': 'M'} + a = Asset.objects.get(id=j_id) + if '...' in j_group[0].split(): + groups = a.bis_group.all() + else: + for group in j_group[0].split(): + c = BisGroup.objects.get(name=group.strip()) + groups.append(c) + + if '...' in j_dept[0].split(): + depts = a.dept.all() + else: + for d in j_dept[0].split(): + p = DEPT.objects.get(name=d.strip()) + depts.append(p) + + j_type = login_types[j_type] + j_idc = IDC.objects.get(name=j_idc) + if j_type == 'M': + if a.password != j_password: + j_password = cryptor.decrypt(j_password) + a.ip = j_ip + a.port = j_port + a.login_type = j_type + a.idc = j_idc + a.is_active = j_active + a.comment = j_comment + a.username = j_user + a.password = j_password + else: + a.ip = j_ip + a.port = j_port + a.idc = j_idc + a.login_type = j_type + a.is_active = is_active[j_active] + a.comment = j_comment + a.save() + a.bis_group = groups + a.dept = depts + a.save() + + +def db_host_delete(request, host_id): + """ 删除主机操作 """ + if is_group_admin(request) and not validate(request, asset=[host_id]): + return httperror(request, '删除失败, 您无权删除!') + + asset = Asset.objects.filter(id=host_id) + if asset: + asset.delete() + else: + return httperror(request, '删除失败, 没有此主机!') + + +def db_idc_delete(request, idc_id): + """ 删除IDC操作 """ + if idc_id == 1: + return httperror(request, '删除失败, 默认IDC不能删除!') + + default_idc = IDC.objects.get(id=1) + + idc = IDC.objects.filter(id=idc_id) + if idc: + idc_class = idc.first() + idc_class.asset_set.update(idc=default_idc) + idc.delete() + else: + return httperror(request, '删除失败, 没有这个IDC!') + + +@require_admin +def host_add(request): + """ 添加主机 """ + header_title, path1, path2 = u'添加主机', u'资产管理', u'添加主机' + login_types = {'L': 'LDAP', 'M': 'MAP'} + eidc = IDC.objects.exclude(name='ALL') + if is_super_user(request): + edept = DEPT.objects.all() + egroup = BisGroup.objects.exclude(name='ALL') + elif is_group_admin(request): + dept = get_session_user_info(request)[5] + egroup = dept.bisgroup_set.all() + + if request.method == 'POST': + j_ip = request.POST.get('j_ip') + j_idc = request.POST.get('j_idc') + j_port = request.POST.get('j_port') + j_type = request.POST.get('j_type') + j_group = request.POST.getlist('j_group') + j_active = request.POST.get('j_active') + j_comment = request.POST.get('j_comment') + + if is_super_user(request): + j_dept = request.POST.getlist('j_dept') + host_info = [j_ip, j_port, j_idc, j_type, j_group, j_dept, j_active, j_comment] + elif is_group_admin(request): + j_dept = request.POST.get('j_dept') + host_info = [j_ip, j_port, j_idc, j_type, j_group, [j_dept], j_active, j_comment] + + if is_group_admin(request) and not validate(request, asset_group=j_group, edept=[j_dept]): + return httperror(request, u'添加失败,您无权操作!') + + if Asset.objects.filter(ip=str(j_ip)): + emg = u'该IP %s 已存在!' % j_ip + return my_render('jasset/host_add.html', locals(), request) + if j_type == 'M': + j_user = request.POST.get('j_user') + j_password = request.POST.get('j_password', '') + db_host_insert(host_info, j_user, j_password) + else: + db_host_insert(host_info) + smg = u'主机 %s 添加成功' % j_ip + + return my_render('jasset/host_add.html', locals(), request) + + +@require_admin +def host_add_batch(request): + """ 批量添加主机 """ + header_title, path1, path2 = u'批量添加主机', u'资产管理', u'批量添加主机' + login_types = {'LDAP': 'L', 'MAP': 'M'} + active_types = {'激活': 1, '禁用': 0} + dept_id = get_user_dept(request) + if request.method == 'POST': + multi_hosts = request.POST.get('j_multi').split('\n') + for host in multi_hosts: + if host == '': + break + j_ip, j_port, j_type, j_idc, j_groups, j_depts, j_active, j_comment = host.split() + j_active = active_types[str(j_active)] + j_group = ast.literal_eval(j_groups) + j_dept = ast.literal_eval(j_depts) + + if j_type not in ['LDAP', 'MAP']: + return httperror(request, u'没有%s这种登录方式!' %j_type) + + j_type = login_types[j_type] + idc = IDC.objects.filter(name=j_idc) + if idc: + j_idc = idc[0].id + else: + return httperror(request, '添加失败, 没有%s这个IDC' % j_idc) + + group_ids, dept_ids = [], [] + for group_name in j_group: + group = BisGroup.objects.filter(name=group_name) + if group: + group_id = group[0].id + else: + return httperror(request, '添加失败, 没有%s这个主机组' % group_name) + group_ids.append(group_id) + + for dept_name in j_dept: + dept = DEPT.objects.filter(name=dept_name) + if dept: + dept_id = dept[0].id + else: + return httperror(request, '添加失败, 没有%s这个部门' % dept_name) + dept_ids.append(dept_id) + + if is_group_admin(request) and not validate(request, asset_group=group_ids, edept=dept_ids): + return httperror(request, '添加失败, 没有%s这个主机组' % group_name) + + if Asset.objects.filter(ip=str(j_ip)): + return httperror(request, '添加失败, 改IP%s已存在' % j_ip) + + host_info = [j_ip, j_port, j_idc, j_type, group_ids, dept_ids, j_active, j_comment] + db_host_insert(host_info) + + smg = u'批量添加添加成功' + return my_render('jasset/host_add_multi.html', locals(), request) + + return my_render('jasset/host_add_multi.html', locals(), request) + + +@require_admin +def host_edit_batch(request): + """ 批量修改主机 """ + if request.method == 'POST': + len_table = request.POST.get('len_table') + for i in range(int(len_table)): + j_id = "editable[" + str(i) + "][j_id]" + j_ip = "editable[" + str(i) + "][j_ip]" + j_port = "editable[" + str(i) + "][j_port]" + j_dept = "editable[" + str(i) + "][j_dept]" + j_idc = "editable[" + str(i) + "][j_idc]" + j_type = "editable[" + str(i) + "][j_type]" + j_group = "editable[" + str(i) + "][j_group]" + j_active = "editable[" + str(i) + "][j_active]" + j_comment = "editable[" + str(i) + "][j_comment]" + + j_id = request.POST.get(j_id).strip() + j_ip = request.POST.get(j_ip).strip() + j_port = request.POST.get(j_port).strip() + j_dept = request.POST.getlist(j_dept) + j_idc = request.POST.get(j_idc).strip() + j_type = request.POST.get(j_type).strip() + j_group = request.POST.getlist(j_group) + j_active = request.POST.get(j_active).strip() + j_comment = request.POST.get(j_comment).strip() + + host_info = [j_id, j_ip, j_idc, j_port, j_type, j_group, j_dept, j_active, j_comment] + batch_host_edit(host_info) + + return HttpResponseRedirect('/jasset/host_list/') + + +@require_login +def host_edit_common_batch(request): + """ 普通用户批量修改主机别名 """ + u = get_session_user_info(request)[2] + if request.method == 'POST': + len_table = request.POST.get('len_table') + for i in range(int(len_table)): + j_id = "editable[" + str(i) + "][j_id]" + j_alias = "editable[" + str(i) + "][j_alias]" + j_id = request.POST.get(j_id, '').strip() + j_alias = request.POST.get(j_alias, '').strip() + a = Asset.objects.get(id=j_id) + asset_alias = AssetAlias.objects.filter(user=u, host=a) + if asset_alias: + asset_alias = asset_alias[0] + asset_alias.alias = j_alias + asset_alias.save() + else: + AssetAlias.objects.create(user=u, host=a, alias=j_alias) + return my_render('jasset/host_list_common.html') + + +@require_login +def host_list(request): + """ 列出主机 """ + header_title, path1, path2 = u'查看主机', u'资产管理', u'查看主机' + keyword = request.GET.get('keyword', '') + dept_id = get_session_user_info(request)[3] + dept = DEPT.objects.get(id=dept_id) + did = request.GET.get('did', '') + gid = request.GET.get('gid', '') + sid = request.GET.get('sid', '') + user_id = get_session_user_info(request)[0] + + post_all = Asset.objects.all().order_by('ip') + post_keyword_all = Asset.objects.filter(Q(ip__contains=keyword) | + Q(idc__name__contains=keyword) | + Q(bis_group__name__contains=keyword) | + Q(comment__contains=keyword)).distinct().order_by('ip') + if did: + if is_common_user(request): + return httperror(request, u'您无权查看!') + + if is_group_admin(request): + user, dept = get_session_user_dept(request) + else: + dept = DEPT.objects.get(id=did) + posts = dept.asset_set.all() + return my_render('jasset/host_list_nop.html', locals(), request) + + elif gid: + if is_common_user(request): + return httperror(request, u'您无权查看!') + + elif is_group_admin(request) and not validate(request, user_group=[gid]): + return httperror(request, u'您无权查看!') + + posts = [] + user_group = UserGroup.objects.filter(id=gid) + if user_group: + perms = Perm.objects.filter(user_group=user_group) + for perm in perms: + for post in perm.asset_group.asset_set.all(): + posts.append(post) + posts = list(set(posts)) + else: + return httperror(request, u'没有这个小组!') + return my_render('jasset/host_list_nop.html', locals(), request) + + elif sid: + if is_common_user(request): + return httperror(request, u'您无权查看!') + + elif is_group_admin(request) and not validate(request, user_group=[sid]): + return httperror(request, u'您无权查看!') + + posts, asset_groups = [], [] + user_group = UserGroup.objects.filter(id=int(sid)) + if user_group: + user_group = user_group[0] + for perm in user_group.sudoperm_set.all(): + asset_groups.extend(perm.asset_group.all()) + + for asset_group in asset_groups: + posts.extend(asset_group.asset_set.all()) + posts = list(set(posts)) + else: + return httperror(request, u'没有这个sudo授权!') + return my_render('jasset/host_list_nop.html', locals(), request) + + else: + if is_super_user(request): + if keyword: + posts = post_keyword_all + else: + posts = post_all + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) + return my_render('jasset/host_list.html', locals(), request) + + elif is_group_admin(request): + if keyword: + posts = post_keyword_all.filter(dept=dept) + else: + posts = post_all.filter(dept=dept) + + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) + return my_render('jasset/host_list.html', locals(), request) + + elif is_common_user(request): + user_id, username = get_session_user_info(request)[0:2] + posts = user_perm_asset_api(username) + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) + return my_render('jasset/host_list_common.html', locals(), request) + + +@require_admin +def host_del(request, offset): + """ 删除主机 """ + if offset == 'multi': + len_list = request.POST.get("len_list") + for i in range(int(len_list)): + key = "id_list[" + str(i) + "]" + host_id = request.POST.get(key) + db_host_delete(request, host_id) + else: + db_host_delete(request, offset) + + return HttpResponseRedirect('/jasset/host_list/') + + +@require_super_user +def host_edit(request): + """ 修改主机 """ + header_title, path1, path2 = u'修改主机', u'资产管理', u'修改主机' + actives = {1: u'激活', 0: u'禁用'} + login_types = {'L': 'LDAP', 'M': 'MAP'} + eidc = IDC.objects.all() + egroup = BisGroup.objects.exclude(name='ALL') + edept = DEPT.objects.all() + host_id = request.GET.get('id', '') + post = Asset.objects.filter(id=int(host_id)) + if post: + post = post[0] + else: + return httperror(request, '没有此主机!') + + e_group = post.bis_group.all() + e_dept = post.dept.all() + + if request.method == 'POST': + j_ip = request.POST.get('j_ip', '') + j_idc = request.POST.get('j_idc', '') + j_port = request.POST.get('j_port', '') + j_type = request.POST.get('j_type', '') + j_dept = request.POST.getlist('j_dept', '') + j_group = request.POST.getlist('j_group', '') + j_active = request.POST.get('j_active', '') + j_comment = request.POST.get('j_comment', '') + + host_info = [j_ip, j_port, j_idc, j_type, j_group, j_dept, j_active, j_comment, post] + if j_type == 'M': + j_user = request.POST.get('j_user') + j_password = request.POST.get('j_password') + db_host_update(host_info, j_user, j_password) + else: + db_host_update(host_info) + + smg = u'主机 %s 修改成功' % j_ip + return HttpResponseRedirect('/jasset/host_detail/?id=%s' % host_id) + + return my_render('jasset/host_edit.html', locals(), request) + + +@require_admin +def host_edit_adm(request): + """ 部门管理员修改主机 """ + header_title, path1, path2 = u'修改主机', u'资产管理', u'修改主机' + actives = {1: u'激活', 0: u'禁用'} + login_types = {'L': 'LDAP', 'M': 'MAP'} + eidc = IDC.objects.all() + dept = get_session_user_info(request)[5] + egroup = BisGroup.objects.exclude(name='ALL').filter(dept=dept) + host_id = request.GET.get('id', '') + post = Asset.objects.filter(id=int(host_id)) + if post: + post = post[0] + else: + return httperror(request, '没有此主机!') + + e_group = post.bis_group.all() + + if request.method == 'POST': + j_ip = request.POST.get('j_ip') + j_idc = request.POST.get('j_idc') + j_port = request.POST.get('j_port') + j_type = request.POST.get('j_type') + j_dept = request.POST.getlist('j_dept') + j_group = request.POST.getlist('j_group') + j_active = request.POST.get('j_active') + j_comment = request.POST.get('j_comment') + + host_info = [j_ip, j_port, j_idc, j_type, j_group, j_dept, j_active, j_comment] + + if not validate(request, asset_group=j_group, edept=j_dept): + emg = u'修改失败,您无权操作!' + return my_render('jasset/host_edit.html', locals(), request) + + if j_type == 'M': + j_user = request.POST.get('j_user') + j_password = request.POST.get('j_password') + db_host_update(host_info, j_user, j_password, post) + else: + db_host_update(host_info, post) + + smg = u'主机 %s 修改成功' % j_ip + return HttpResponseRedirect('/jasset/host_detail/?id=%s' % host_id) + + return my_render('jasset/host_edit.html', locals(), request) + + +@require_login +def host_detail(request): + """ 主机详情 """ + header_title, path1, path2 = u'主机详细信息', u'资产管理', u'主机详情' + host_id = request.GET.get('id', '') + post = Asset.objects.filter(id=host_id) + if not post: + return httperror(request, '没有此主机!') + post = post.first() + + if is_group_admin(request) and not validate(request, asset=[host_id]): + return httperror(request, '您无权查看!') + + elif is_common_user(request): + username = get_session_user_info(request)[1] + user_permed_hosts = user_perm_asset_api(username) + if post not in user_permed_hosts: + return httperror(request, '您无权查看!') + else: + log_all = Log.objects.filter(host=post.ip) + log, log_more = log_all[:10], log_all[10:] + user_permed_list = asset_perm_api(post) + + return my_render('jasset/host_detail.html', locals(), request) + + +@require_super_user +def idc_add(request): + """ 添加IDC """ + header_title, path1, path2 = u'添加IDC', u'资产管理', u'添加IDC' + if request.method == 'POST': + j_idc = request.POST.get('j_idc') + j_comment = request.POST.get('j_comment') + if IDC.objects.filter(name=j_idc): + emg = u'该IDC已存在!' + return my_render('jasset/idc_add.html', locals(), request) + else: + smg = u'IDC:%s添加成功' % j_idc + IDC.objects.create(name=j_idc, comment=j_comment) + + return my_render('jasset/idc_add.html', locals(), request) + + +@require_admin +def idc_list(request): + """ 列出IDC """ + header_title, path1, path2 = u'查看IDC', u'资产管理', u'查看IDC' + dept_id = get_user_dept(request) + dept = DEPT.objects.get(id=dept_id) + keyword = request.GET.get('keyword', '') + if keyword: + posts = IDC.objects.filter(Q(name__contains=keyword) | Q(comment__contains=keyword)) + else: + posts = IDC.objects.exclude(name='ALL').order_by('id') + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) + return my_render('jasset/idc_list.html', locals(), request) + + +@require_super_user +def idc_edit(request): + """ 修改IDC """ + header_title, path1, path2 = u'编辑IDC', u'资产管理', u'编辑IDC' + idc_id = request.GET.get('id', '') + idc = IDC.objects.filter(id=idc_id) + if int(idc_id) == 1: + return httperror(request, u'默认IDC不能编辑!') + if idc: + idc = idc[0] + default = IDC.objects.get(id=1).asset_set.all() + eposts = Asset.objects.filter(idc=idc).order_by('ip') + posts = [g for g in default if g not in eposts] + else: + return httperror(request, u'此IDC不存在') + + if request.method == 'POST': + idc_id = request.POST.get('id') + j_idc = request.POST.get('j_idc') + j_hosts = request.POST.getlist('j_hosts') + j_comment = request.POST.get('j_comment') + idc_default = request.POST.getlist('idc_default') + + idc = IDC.objects.filter(id=idc_id) + if idc: + idc.update(name=j_idc, comment=j_comment) + for host_id in j_hosts: + Asset.objects.filter(id=host_id).update(idc=idc[0]) + + i = IDC.objects.get(id=1) + for host in idc_default: + g = Asset.objects.filter(id=host).update(idc=i) + else: + return httperror(request, u'此IDC不存在') + + return HttpResponseRedirect('/jasset/idc_list/?id=%s' % idc_id) + + return my_render('jasset/idc_edit.html', locals(), request) + + +@require_admin +def idc_detail(request): + """ IDC详情 """ + header_title, path1, path2 = u'IDC详情', u'资产管理', u'IDC详情' + login_types = {'L': 'LDAP', 'M': 'MAP'} + idc_id = request.GET.get('id', '') + idc_filter = IDC.objects.filter(id=idc_id) + if idc_filter: + idc = idc_filter[0] + else: + return httperror(request, '没有此IDC') + dept = get_session_user_info(request)[5] + if is_super_user(request): + posts = Asset.objects.filter(idc=idc).order_by('ip') + elif is_group_admin(request): + posts = Asset.objects.filter(idc=idc, dept=dept).order_by('ip') + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) + + return my_render('jasset/idc_detail.html', locals(), request) + + +@require_super_user +def idc_del(request): + """ 删除IDC """ + offset = request.GET.get('id', '') + if offset == 'multi': + len_list = request.POST.get("len_list") + for i in range(int(len_list)): + key = "id_list[" + str(i) + "]" + idc_id = request.POST.get(key) + db_idc_delete(request, int(idc_id)) + else: + db_idc_delete(request, int(offset)) + return HttpResponseRedirect('/jasset/idc_list/') + + +@require_admin +def group_add(request): + """ 添加主机组 """ + header_title, path1, path2 = u'添加主机组', u'资产管理', u'添加主机组' + if is_super_user(request): + posts = Asset.objects.all() + edept = DEPT.objects.all() + elif is_group_admin(request): + dept_id = get_user_dept(request) + dept = DEPT.objects.get(id=dept_id) + posts = Asset.objects.filter(dept=dept) + edept = get_session_user_info(request)[5] + + if request.method == 'POST': + j_group = request.POST.get('j_group', '') + j_dept = request.POST.get('j_dept', '') + j_hosts = request.POST.getlist('j_hosts', '') + j_comment = request.POST.get('j_comment', '') + + try: + if is_group_admin(request) and not validate(request, asset=j_hosts, edept=[j_dept]): + emg = u'添加失败, 您无权操作!' + raise RaiseError + + elif BisGroup.objects.filter(name=j_group): + emg = u'添加失败, 该主机组已存在!' + raise RaiseError + + except RaiseError: + pass + + else: + j_dept = DEPT.objects.filter(id=j_dept).first() + group = BisGroup.objects.create(name=j_group, dept=j_dept, comment=j_comment) + for host in j_hosts: + g = Asset.objects.get(id=host) + group.asset_set.add(g) + smg = u'主机组 %s 添加成功' % j_group + + return my_render('jasset/group_add.html', locals(), request) + + +@require_admin +def group_list(request): + """ 列出主机组 """ + header_title, path1, path2 = u'查看主机组', u'资产管理', u'查看主机组' + dept_id = get_user_dept(request) + dept = DEPT.objects.get(id=dept_id) + keyword = request.GET.get('keyword', '') + gid = request.GET.get('gid') + sid = request.GET.get('sid') + if gid: + if is_common_user(request): + return httperror(request, u'您无权查看!') + + elif is_group_admin(request) and not validate(request, user_group=[gid]): + return httperror(request, u'您无权查看!') + + posts = [] + user_group = UserGroup.objects.filter(id=gid) + if user_group: + user_group = user_group[0] + perms = Perm.objects.filter(user_group=user_group) + for perm in perms: + posts.append(perm.asset_group) + + elif sid: + if is_common_user(request): + return httperror(request, u'您无权查看!') + + elif is_group_admin(request) and not validate(request, user_group=[sid]): + return httperror(request, u'您无权查看!') + + posts = [] + user_group = UserGroup.objects.filter(id=sid) + if user_group: + user_group = user_group[0] + for perm in user_group.sudoperm_set.all(): + posts.extend(perm.asset_group.all()) + posts = list(set(posts)) + else: + return httperror(request, u'没有此sudo授权!') + + else: + if is_super_user(request): + if keyword: + posts = BisGroup.objects.exclude(name='ALL').filter( + Q(name__contains=keyword) | Q(comment__contains=keyword)) + else: + posts = BisGroup.objects.exclude(name='ALL').order_by('id') + elif is_group_admin(request): + if keyword: + posts = BisGroup.objects.filter(Q(name__contains=keyword) | Q(comment__contains=keyword)).filter( + dept=dept) + else: + posts = BisGroup.objects.filter(dept=dept).order_by('id') + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) + return my_render('jasset/group_list.html', locals(), request) + + +@require_admin +def group_edit(request): + """ 修改主机组 """ + header_title, path1, path2 = u'编辑主机组', u'资产管理', u'编辑主机组' + group_id = request.GET.get('id', '') + group = BisGroup.objects.filter(id=group_id) + if group: + group = group.first() + else: + httperror(request, u'没有这个主机组!') + + host_all = Asset.objects.all() + dept_id = get_session_user_info(request)[3] + eposts = Asset.objects.filter(bis_group=group) + + if is_group_admin(request) and not validate(request, asset_group=[group_id]): + return httperror(request, '编辑失败, 您无权操作!') + dept = DEPT.objects.filter(id=group.dept.id) + if dept: + dept = dept[0] + else: + return httperror(request, u'没有这个部门!') + + all_dept = dept.asset_set.all() + posts = [g for g in all_dept if g not in eposts] + + if request.method == 'POST': + j_group = request.POST.get('j_group', '') + j_hosts = request.POST.getlist('j_hosts', '') + j_dept = request.POST.get('j_dept', '') + j_comment = request.POST.get('j_comment', '') + + j_dept = DEPT.objects.filter(id=int(j_dept)) + j_dept = j_dept[0] + + group.asset_set.clear() + for host in j_hosts: + g = Asset.objects.get(id=host) + group.asset_set.add(g) + BisGroup.objects.filter(id=group_id).update(name=j_group, dept=j_dept, comment=j_comment) + smg = u'主机组%s修改成功' % j_group + return HttpResponseRedirect('/jasset/group_list') + + return my_render('jasset/group_edit.html', locals(), request) + + +@require_admin +def group_detail(request): + """ 主机组详情 """ + header_title, path1, path2 = u'主机组详情', u'资产管理', u'主机组详情' + login_types = {'L': 'LDAP', 'M': 'MAP'} + dept = get_session_user_info(request)[5] + group_id = request.GET.get('id', '') + group = BisGroup.objects.get(id=group_id) + if is_super_user(request): + posts = Asset.objects.filter(bis_group=group).order_by('ip') + + elif is_group_admin(request): + if not validate(request, asset_group=[group_id]): + return httperror(request, u'您无权查看!') + posts = Asset.objects.filter(bis_group=group).filter(dept=dept).order_by('ip') + + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) + return my_render('jasset/group_detail.html', locals(), request) + + +@require_admin +def group_del_host(request): + """ 主机组中剔除主机, 并不删除真实主机 """ + if request.method == 'POST': + group_id = request.POST.get('group_id') + offset = request.GET.get('id', '') + group = BisGroup.objects.get(id=group_id) + if offset == 'group': + len_list = request.POST.get("len_list") + for i in range(int(len_list)): + key = "id_list[" + str(i) + "]" + jid = request.POST.get(key) + g = Asset.objects.get(id=jid) + group.asset_set.remove(g) + + else: + offset = request.GET.get('id', '') + group_id = request.GET.get('gid', '') + group = BisGroup.objects.get(id=group_id) + g = Asset.objects.get(id=offset) + group.asset_set.remove(g) + + return HttpResponseRedirect('/jasset/group_detail/?id=%s' % group.id) + + +@require_admin +def group_del(request): + """ 删除主机组 """ + offset = request.GET.get('id', '') + if offset == 'multi': + len_list = request.POST.get("len_list") + for i in range(int(len_list)): + key = "id_list[" + str(i) + "]" + gid = request.POST.get(key) + if is_group_admin(request) and not validate(request, asset_group=[gid]): + return httperror(request, '删除失败, 您无权删除!') + BisGroup.objects.filter(id=gid).delete() + else: + gid = int(offset) + if is_group_admin(request) and not validate(request, asset_group=[gid]): + return httperror(request, '删除失败, 您无权删除!') + BisGroup.objects.filter(id=gid).delete() + return HttpResponseRedirect('/jasset/group_list/') + + +@require_admin +def dept_host_ajax(request): + """ 添加主机组时, 部门联动主机异步 """ + dept_id = request.GET.get('id', '') + if dept_id not in ['1', '2']: + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept = dept[0] + hosts = dept.asset_set.all() + else: + hosts = Asset.objects.all() + + return my_render('jasset/dept_host_ajax.html', locals(), request) + + +def show_all_ajax(request): + """ 批量修改主机时, 部门和组全部显示 """ + env = request.GET.get('env', '') + get_id = request.GET.get('id', '') + host = Asset.objects.filter(id=get_id) + if host: + host = host[0] + return my_render('jasset/show_all_ajax.html', locals(), request) + + +@require_login +def host_search(request): + """ 搜索主机 """ + keyword = request.GET.get('keyword') + login_types = {'L': 'LDAP', 'M': 'MAP'} + dept = get_session_user_info(request)[5] + post_all = Asset.objects.filter(Q(ip__contains=keyword) | + Q(idc__name__contains=keyword) | + Q(bis_group__name__contains=keyword) | + Q(comment__contains=keyword)).distinct().order_by('ip') + if is_super_user(request): + posts = post_all + + elif is_group_admin(request): + posts = post_all.filter(dept=dept) + + elif is_common_user(request): + username = get_session_user_info(request)[2] + post_perm = user_perm_asset_api(username) + posts = list(set(post_all) & set(post_perm)) + + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) + + return my_render('jasset/host_search.html', locals(), request) \ No newline at end of file diff --git a/webroot/AutoSa/AutoSa/__init__.py b/jlog/__init__.py similarity index 100% rename from webroot/AutoSa/AutoSa/__init__.py rename to jlog/__init__.py diff --git a/webroot/AutoSa/UserManage/admin.py b/jlog/admin.py similarity index 100% rename from webroot/AutoSa/UserManage/admin.py rename to jlog/admin.py diff --git a/jlog/models.py b/jlog/models.py new file mode 100644 index 000000000000..0e22c5d075be --- /dev/null +++ b/jlog/models.py @@ -0,0 +1,17 @@ +from django.db import models + + +class Log(models.Model): + user = models.CharField(max_length=20, null=True) + host = models.CharField(max_length=20, null=True) + remote_ip = models.CharField(max_length=100) + dept_name = models.CharField(max_length=20) + log_path = models.CharField(max_length=100) + start_time = models.DateTimeField(null=True) + pid = models.IntegerField(max_length=10) + is_finished = models.BooleanField(default=False) + log_finished = models.BooleanField(default=False) + end_time = models.DateTimeField(null=True) + + def __unicode__(self): + return self.log_path \ No newline at end of file diff --git a/webroot/AutoSa/UserManage/tests.py b/jlog/tests.py similarity index 100% rename from webroot/AutoSa/UserManage/tests.py rename to jlog/tests.py diff --git a/jlog/urls.py b/jlog/urls.py new file mode 100644 index 000000000000..0b6810d3cad2 --- /dev/null +++ b/jlog/urls.py @@ -0,0 +1,11 @@ +# coding:utf-8 +from django.conf.urls import patterns, include, url +from jlog.views import * + +urlpatterns = patterns('', + url(r'^$', log_list), + url(r'^log_list/(\w+)/$', log_list), + url(r'^log_kill/', log_kill), + url(r'^history/$', log_history), + url(r'^search/$', log_search), +) \ No newline at end of file diff --git a/jlog/views.py b/jlog/views.py new file mode 100644 index 000000000000..85a937028897 --- /dev/null +++ b/jlog/views.py @@ -0,0 +1,117 @@ +# coding:utf-8 +from django.db.models import Q +from django.template import RequestContext +from django.shortcuts import render_to_response + +from jumpserver.api import * +from jasset.views import httperror +from django.http import HttpResponseNotFound + +CONF = ConfigParser() +CONF.read('%s/jumpserver.conf' % BASE_DIR) + + +def get_user_info(request, offset): + """ 获取用户信息及环境 """ + env_dic = {'online': 0, 'offline': 1} + env = env_dic[offset] + keyword = request.GET.get('keyword', '') + user_info = get_session_user_info(request) + user_id, username = user_info[0:2] + dept_id, dept_name = user_info[3:5] + ret = [request, keyword, env, username, dept_name] + + return ret + + +def get_user_log(ret_list): + """ 获取不同类型用户日志记录 """ + request, keyword, env, username, dept_name = ret_list + post_all = Log.objects.filter(is_finished=env).order_by('-start_time') + post_keyword_all = Log.objects.filter(Q(user__contains=keyword) | + Q(host__contains=keyword)) \ + .filter(is_finished=env).order_by('-start_time') + + if is_super_user(request): + if keyword: + posts = post_keyword_all + else: + posts = post_all + + elif is_group_admin(request): + if keyword: + posts = post_keyword_all.filter(dept_name=dept_name) + else: + posts = post_all.filter(dept_name=dept_name) + + elif is_common_user(request): + if keyword: + posts = post_keyword_all.filter(user=username) + else: + posts = post_all.filter(user=username) + + return posts + + +@require_login +def log_list(request, offset): + """ 显示日志 """ + header_title, path1, path2 = u'查看日志', u'查看日志', u'在线用户' + keyword = request.GET.get('keyword', '') + web_socket_host = CONF.get('websocket', 'web_socket_host') + posts = get_user_log(get_user_info(request, offset)) + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) + + return render_to_response('jlog/log_%s.html' % offset, locals(), context_instance=RequestContext(request)) + + +@require_admin +def log_kill(request): + """ 杀掉connect进程 """ + pid = request.GET.get('id', '') + log = Log.objects.filter(pid=pid) + if log: + log = log.first() + dept_name = log.dept_name + deptname = get_session_user_info(request)[4] + if is_group_admin(request) and dept_name != deptname: + return httperror(request, u'Kill失败, 您无权操作!') + os.kill(int(pid), 9) + Log.objects.filter(pid=pid).update(is_finished=1, end_time=datetime.datetime.now()) + return render_to_response('jlog/log_offline.html', locals(), context_instance=RequestContext(request)) + else: + return HttpResponseNotFound(u'没有此进程!') + + +@require_login +def log_history(request): + """ 命令历史记录 """ + log_id = request.GET.get('id', 0) + log = Log.objects.filter(id=int(log_id)) + if log: + log = log.first() + dept_name = log.dept_name + deptname = get_session_user_info(request)[4] + if is_group_admin(request) and dept_name != deptname: + return httperror(request, '查看失败, 您无权查看!') + + elif is_common_user(request): + return httperror(request, '查看失败, 您无权查看!') + + log_his = "%s.his" % log.log_path + if os.path.isfile(log_his): + f = open(log_his) + content = f.read() + return HttpResponse(content) + else: + return httperror(request, '无日志记录, 请查看日志处理脚本是否开启!') + + +@require_login +def log_search(request): + """ 日志搜索 """ + offset = request.GET.get('env', '') + keyword = request.GET.get('keyword', '') + posts = get_user_log(get_user_info(request, offset)) + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) + return render_to_response('jlog/log_search.html', locals(), context_instance=RequestContext(request)) diff --git a/webroot/AutoSa/AutoSa/templatetags/__init__.py b/jperm/__init__.py similarity index 100% rename from webroot/AutoSa/AutoSa/templatetags/__init__.py rename to jperm/__init__.py diff --git a/jperm/admin.py b/jperm/admin.py new file mode 100644 index 000000000000..8c38f3f3dad5 --- /dev/null +++ b/jperm/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/jperm/models.py b/jperm/models.py new file mode 100644 index 000000000000..c29cb8e54849 --- /dev/null +++ b/jperm/models.py @@ -0,0 +1,54 @@ +import datetime + +from uuidfield import UUIDField + +from django.db import models +from juser.models import UserGroup, DEPT +from jasset.models import Asset, BisGroup + + +class Perm(models.Model): + user_group = models.ForeignKey(UserGroup) + asset_group = models.ForeignKey(BisGroup) + + def __unicode__(self): + return '%s_%s' % (self.user_group.name, self.asset_group.name) + + +class CmdGroup(models.Model): + name = models.CharField(max_length=50, unique=True) + cmd = models.CharField(max_length=999) + dept = models.ForeignKey(DEPT) + comment = models.CharField(blank=True, null=True, max_length=50) + + def __unicode__(self): + return self.name + + +class SudoPerm(models.Model): + user_group = models.ForeignKey(UserGroup) + user_runas = models.CharField(max_length=100) + asset_group = models.ManyToManyField(BisGroup) + cmd_group = models.ManyToManyField(CmdGroup) + comment = models.CharField(max_length=30, null=True, blank=True) + + def __unicode__(self): + return self.user_group.name + + +class Apply(models.Model): + uuid = UUIDField(auto=True) + applyer = models.CharField(max_length=20) + admin = models.CharField(max_length=20) + approver = models.CharField(max_length=20) + dept = models.CharField(max_length=20) + bisgroup = models.CharField(max_length=500) + asset = models.CharField(max_length=500) + comment = models.TextField(blank=True, null=True) + status = models.IntegerField(max_length=2) + date_add = models.DateTimeField(null=True) + date_end = models.DateTimeField(null=True) + read = models.IntegerField(max_length=2) + + def __unicode__(self): + return self.applyer diff --git a/jperm/tests.py b/jperm/tests.py new file mode 100644 index 000000000000..7ce503c2dd97 --- /dev/null +++ b/jperm/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/jperm/urls.py b/jperm/urls.py new file mode 100644 index 000000000000..41a7b26eddfe --- /dev/null +++ b/jperm/urls.py @@ -0,0 +1,33 @@ +from django.conf.urls import patterns, include, url +from jperm.views import * + +urlpatterns = patterns('jperm.views', + # Examples: + # url(r'^$', 'jumpserver.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + + (r'^perm_edit/$', view_splitter, {'su': perm_edit, 'adm': perm_edit_adm}), + (r'^dept_perm_edit/$', 'dept_perm_edit'), + (r'^perm_list/$', view_splitter, {'su': perm_list, 'adm': perm_list_adm}), + (r'^dept_perm_list/$', 'dept_perm_list'), + (r'^perm_user_detail/$', 'perm_user_detail'), + (r'^perm_detail/$', 'perm_detail'), + (r'^perm_del/$', 'perm_del'), + (r'^perm_asset_detail/$', 'perm_asset_detail'), + (r'^sudo_list/$', view_splitter, {'su': sudo_list, 'adm': sudo_list_adm}), + (r'^sudo_del/$', 'sudo_del'), + (r'^sudo_edit/$', view_splitter, {'su': sudo_edit, 'adm': sudo_edit_adm}), + (r'^sudo_refresh/$', 'sudo_refresh'), + (r'^sudo_detail/$', 'sudo_detail'), + (r'^cmd_add/$', view_splitter, {'su': cmd_add, 'adm': cmd_add_adm}), + (r'^cmd_list/$', 'cmd_list'), + (r'^cmd_del/$', 'cmd_del'), + (r'^cmd_edit/$', 'cmd_edit'), + (r'^cmd_detail/$', 'cmd_detail'), + (r'^apply/$', 'perm_apply'), + (r'^apply_show/(\w+)/$', 'perm_apply_log'), + (r'^apply_exec/$', 'perm_apply_exec'), + (r'^apply_info/$', 'perm_apply_info'), + (r'^apply_del/$', 'perm_apply_del'), + (r'^apply_search/$', 'perm_apply_search'), +) diff --git a/jperm/views.py b/jperm/views.py new file mode 100644 index 000000000000..d6d6bf2c38fb --- /dev/null +++ b/jperm/views.py @@ -0,0 +1,813 @@ +# coding: utf-8 +import sys + +reload(sys) +sys.setdefaultencoding('utf8') + +from django.shortcuts import render_to_response +from django.template import RequestContext +from jperm.models import Perm, SudoPerm, CmdGroup, Apply +from django.db.models import Q +from jumpserver.api import * + + +def asset_cmd_groups_get(asset_groups_select='', cmd_groups_select=''): + asset_groups_select_list = [] + cmd_groups_select_list = [] + + for asset_group_id in asset_groups_select: + asset_groups_select_list.extend(BisGroup.objects.filter(id=asset_group_id)) + + for cmd_group_id in cmd_groups_select: + cmd_groups_select_list.extend(CmdGroup.objects.filter(id=cmd_group_id)) + + return asset_groups_select_list, cmd_groups_select_list + + +@require_admin +def perm_add(request): + header_title, path1, path2 = u'主机授权添加', u'授权管理', u'授权添加' + + if request.method == 'GET': + user_groups = UserGroup.objects.filter(id__gt=2) + asset_groups = BisGroup.objects.all() + + else: + name = request.POST.get('name', '') + user_groups_select = request.POST.getlist('user_groups_select') + asset_groups_select = request.POST.getlist('asset_groups_select') + comment = request.POST.get('comment', '') + + user_groups, asset_groups = user_asset_cmd_groups_get(user_groups_select, asset_groups_select, '')[0:2] + + perm = Perm(name=name, comment=comment) + perm.save() + + perm.user_group = user_groups + perm.asset_group = asset_groups + msg = '添加成功' + return render_to_response('jperm/perm_add.html', locals(), context_instance=RequestContext(request)) + + +def dept_add_asset(dept_id, asset_list): + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept = dept[0] + new_perm_asset = [] + for asset_id in asset_list: + asset = Asset.objects.filter(id=asset_id) + new_perm_asset.extend(asset) + + dept.asset_set.clear() + dept.asset_set = new_perm_asset + + +@require_super_user +def dept_perm_edit(request): + header_title, path1, path2 = u'部门授权添加', u'授权管理', u'部门授权添加' + if request.method == 'GET': + dept_id = request.GET.get('id', '') + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept = dept[0] + asset_all = Asset.objects.all() + asset_select = dept.asset_set.all() + assets = [asset for asset in asset_all if asset not in asset_select] + else: + dept_id = request.POST.get('dept_id') + asset_select = request.POST.getlist('asset_select') + dept_add_asset(dept_id, asset_select) + return HttpResponseRedirect('/jperm/dept_perm_list/') + return render_to_response('jperm/dept_perm_edit.html', locals(), context_instance=RequestContext(request)) + + +@require_super_user +def perm_list(request): + header_title, path1, path2 = u'小组授权', u'授权管理', u'授权详情' + keyword = request.GET.get('search', '') + uid = request.GET.get('uid', '') + agid = request.GET.get('agid', '') + if keyword: + contact_list = UserGroup.objects.filter(Q(name__icontains=keyword) | Q(comment__icontains=keyword)) + else: + contact_list = UserGroup.objects.all().order_by('name') + + if uid: + user = User.objects.filter(id=uid) + print user + if user: + user = user[0] + contact_list = contact_list.filter(user=user) + + if agid: + contact_list_confirm = [] + asset_group = BisGroup.objects.filter(id=agid) + if asset_group: + asset_group = asset_group[0] + for user_group in contact_list: + if asset_group in user_group_perm_asset_group_api(user_group): + contact_list_confirm.append(user_group) + contact_list = contact_list_confirm + + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(contact_list, request) + return render_to_response('jperm/perm_list.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def perm_list_adm(request): + header_title, path1, path2 = u'小组授权', u'授权管理', u'授权详情' + keyword = request.GET.get('search', '') + uid = request.GET.get('uid', '') + agid = request.GET.get('agid', '') + user, dept = get_session_user_dept(request) + contact_list = dept.usergroup_set.all().order_by('name') + if keyword: + contact_list = contact_list.filter(Q(name__icontains=keyword) | Q(comment__icontains=keyword)) + + if uid: + user = User.objects.filter(id=uid) + print user + if user: + user = user[0] + contact_list = contact_list.filter(user=user) + + if agid: + contact_list_confirm = [] + asset_group = BisGroup.objects.filter(id=agid) + if asset_group: + asset_group = asset_group[0] + for user_group in contact_list: + if asset_group in user_group_perm_asset_group_api(user_group): + contact_list_confirm.append(user_group) + contact_list = contact_list_confirm + + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(contact_list, request) + return render_to_response('jperm/perm_list.html', locals(), context_instance=RequestContext(request)) + + +@require_super_user +def dept_perm_list(request): + header_title, path1, path2 = '查看部门', '授权管理', '部门授权' + keyword = request.GET.get('search') + if keyword: + contact_list = DEPT.objects.filter(Q(name__icontains=keyword) | Q(comment__icontains=keyword)).order_by('name') + else: + contact_list = DEPT.objects.filter(id__gt=2) + + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(contact_list, request) + + return render_to_response('jperm/dept_perm_list.html', locals(), context_instance=RequestContext(request)) + + +def perm_group_update(user_group_id, asset_groups_id_list): + user_group = UserGroup.objects.filter(id=user_group_id) + if user_group: + user_group = user_group[0] + old_asset_group = [perm.asset_group for perm in user_group.perm_set.all()] + new_asset_group = [] + + for asset_group_id in asset_groups_id_list: + new_asset_group.extend(BisGroup.objects.filter(id=asset_group_id)) + + del_asset_group = [asset_group for asset_group in old_asset_group if asset_group not in new_asset_group] + add_asset_group = [asset_group for asset_group in new_asset_group if asset_group not in old_asset_group] + + for asset_group in del_asset_group: + Perm.objects.filter(user_group=user_group, asset_group=asset_group).delete() + + for asset_group in add_asset_group: + Perm(user_group=user_group, asset_group=asset_group).save() + + +@require_super_user +def perm_edit(request): + if request.method == 'GET': + header_title, path1, path2 = u'编辑授权', u'授权管理', u'授权编辑' + user_group_id = request.GET.get('id', '') + user_group = UserGroup.objects.filter(id=user_group_id) + if user_group: + user_group = user_group[0] + asset_groups_all = BisGroup.objects.all() + asset_groups_select = [perm.asset_group for perm in user_group.perm_set.all()] + asset_groups = [asset_group for asset_group in asset_groups_all if asset_group not in asset_groups_select] + else: + user_group_id = request.POST.get('user_group_id') + asset_group_id_list = request.POST.getlist('asset_groups_select') + perm_group_update(user_group_id, asset_group_id_list) + + return HttpResponseRedirect('/jperm/perm_list/') + return render_to_response('jperm/perm_edit.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def perm_edit_adm(request): + if request.method == 'GET': + header_title, path1, path2 = u'编辑授权', u'授权管理', u'授权编辑' + user_group_id = request.GET.get('id', '') + user_group = UserGroup.objects.filter(id=user_group_id) + user, dept = get_session_user_dept(request) + if user_group: + user_group = user_group[0] + asset_groups_all = dept.bisgroup_set.all() + asset_groups_select = [perm.asset_group for perm in user_group.perm_set.all()] + asset_groups = [asset_group for asset_group in asset_groups_all if asset_group not in asset_groups_select] + else: + user_group_id = request.POST.get('user_group_id') + asset_group_id_list = request.POST.getlist('asset_groups_select') + print user_group_id, asset_group_id_list + if not validate(request, user_group=[user_group_id], asset_group=asset_group_id_list): + return HttpResponseRedirect('/') + perm_group_update(user_group_id, asset_group_id_list) + + return HttpResponseRedirect('/jperm/perm_list/') + return render_to_response('jperm/perm_edit.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def perm_detail(request): + header_title, path1, path2 = u'授权管理', u'小组管理', u'授权详情' + group_id = request.GET.get('id') + user_group = UserGroup.objects.filter(id=group_id) + if user_group: + user_group = user_group[0] + users = user_group.user_set.all() + group_user_num = len(users) + perms = user_group.perm_set.all() + asset_groups = [perm.asset_group for perm in perms] + return render_to_response('jperm/perm_detail.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def perm_del(request): + perm_id = request.GET.get('id') + perm = Perm.objects.filter(id=perm_id) + if perm: + perm = perm[0] + perm.delete() + return HttpResponseRedirect('/jperm/perm_list/') + + +@require_admin +def perm_asset_detail(request): + header_title, path1, path2 = u'用户授权主机', u'权限管理', u'用户主机详情' + user_id = request.GET.get('id') + user = User.objects.filter(id=user_id) + if user: + user = user[0] + assets_list = user_perm_asset_api(user.username) + return render_to_response('jperm/perm_asset_detail.html', locals(), context_instance=RequestContext(request)) + + +def unicode2str(unicode_list): + return [str(i) for i in unicode_list] + + +def sudo_ldap_add(user_group, user_runas, asset_groups_select, + cmd_groups_select): + if not LDAP_ENABLE: + return True + + assets = [] + cmds = [] + user_runas = user_runas.split(',') + if len(asset_groups_select) == 1 and asset_groups_select[0].name == 'ALL': + asset_all = True + else: + asset_all = False + for asset_group in asset_groups_select: + assets.extend(asset_group.asset_set.all()) + + if user_group.name == 'ALL': + user_all = True + users = [] + else: + user_all = False + users = user_group.user_set.all() + + for cmd_group in cmd_groups_select: + cmds.extend(cmd_group.cmd.split(',')) + + if user_all: + users_name = ['ALL'] + else: + users_name = list(set([user.username for user in users])) + + if asset_all: + assets_ip = ['ALL'] + else: + assets_ip = list(set([asset.ip for asset in assets])) + + name = 'sudo%s' % user_group.id + sudo_dn = 'cn=%s,ou=Sudoers,%s' % (name, LDAP_BASE_DN) + sudo_attr = {'objectClass': ['top', 'sudoRole'], + 'cn': ['%s' % name], + 'sudoCommand': unicode2str(cmds), + 'sudoHost': unicode2str(assets_ip), + 'sudoOption': ['!authenticate'], + 'sudoRunAsUser': unicode2str(user_runas), + 'sudoUser': unicode2str(users_name)} + ldap_conn.delete(sudo_dn) + ldap_conn.add(sudo_dn, sudo_attr) + + +def sudo_update(user_group, user_runas, asset_groups_select, cmd_groups_select, comment): + asset_groups_select_list, cmd_groups_select_list = \ + asset_cmd_groups_get(asset_groups_select, cmd_groups_select) + sudo_perm = user_group.sudoperm_set.all() + if sudo_perm: + sudo_perm.update(user_runas=user_runas, comment=comment) + sudo_perm = sudo_perm[0] + sudo_perm.asset_group = asset_groups_select_list + sudo_perm.cmd_group = cmd_groups_select_list + else: + sudo_perm = SudoPerm(user_group=user_group, user_runas=user_runas, comment=comment) + sudo_perm.save() + sudo_perm.asset_group = asset_groups_select_list + sudo_perm.cmd_group = cmd_groups_select_list + + sudo_ldap_add(user_group, user_runas, asset_groups_select_list, cmd_groups_select_list) + + +@require_super_user +def sudo_list(request): + header_title, path1, path2 = u'Sudo授权', u'权限管理', u'Sudo权限详情' + keyword = request.GET.get('search', '') + contact_list = UserGroup.objects.all().order_by('name') + if keyword: + contact_list = contact_list.filter(Q(name__icontains=keyword) | Q(comment__icontains=keyword)) + + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(contact_list, request) + return render_to_response('jperm/sudo_list.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def sudo_list_adm(request): + header_title, path1, path2 = u'Sudo授权', u'权限管理', u'Sudo权限详情' + keyword = request.GET.get('search', '') + user, dept = get_session_user_dept(request) + contact_list = dept.usergroup_set.all().order_by('name') + if keyword: + contact_list = contact_list.filter(Q(name__icontains=keyword) | Q(comment__icontains=keyword)) + + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(contact_list, request) + return render_to_response('jperm/sudo_list.html', locals(), context_instance=RequestContext(request)) + + +@require_super_user +def sudo_edit(request): + header_title, path1, path2 = u'Sudo授权', u'授权管理', u'Sudo授权' + + if request.method == 'GET': + user_group_id = request.GET.get('id', '0') + user_group = UserGroup.objects.filter(id=user_group_id) + asset_group_all = BisGroup.objects.filter() + cmd_group_all = CmdGroup.objects.all() + if user_group: + user_group = user_group[0] + sudo_perm = user_group.sudoperm_set.all() + if sudo_perm: + sudo_perm = sudo_perm[0] + asset_group_permed = sudo_perm.asset_group.all() + cmd_group_permed = sudo_perm.cmd_group.all() + user_runas = sudo_perm.user_runas + comment = sudo_perm.comment + else: + asset_group_permed = [] + cmd_group_permed = [] + + asset_groups = [asset_group for asset_group in asset_group_all if asset_group not in asset_group_permed] + cmd_groups = [cmd_group for cmd_group in cmd_group_all if cmd_group not in cmd_group_permed] + + else: + user_group_id = request.POST.get('user_group_id', '') + users_runas = request.POST.get('runas', 'root') + asset_groups_select = request.POST.getlist('asset_groups_select') + cmd_groups_select = request.POST.getlist('cmd_groups_select') + comment = request.POST.get('comment', '') + user_group = UserGroup.objects.filter(id=user_group_id) + if user_group: + user_group = user_group[0] + if LDAP_ENABLE: + sudo_update(user_group, users_runas, asset_groups_select, cmd_groups_select, comment) + msg = '修改成功' + + return HttpResponseRedirect('/jperm/sudo_list/') + + return render_to_response('jperm/sudo_edit.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def sudo_edit_adm(request): + header_title, path1, path2 = u'Sudo授权', u'授权管理', u'Sudo授权' + user, dept = get_session_user_dept(request) + if request.method == 'GET': + user_group_id = request.GET.get('id', '0') + if not validate(request, user_group=[user_group_id]): + return render_to_response('/jperm/sudo_list/') + user_group = UserGroup.objects.filter(id=user_group_id) + asset_group_all = dept.bisgroup_set.all() + cmd_group_all = dept.cmdgroup_set.all() + if user_group: + user_group = user_group[0] + sudo_perm = user_group.sudoperm_set.all() + if sudo_perm: + sudo_perm = sudo_perm[0] + asset_group_permed = sudo_perm.asset_group.all() + cmd_group_permed = sudo_perm.cmd_group.all() + user_runas = sudo_perm.user_runas + comment = sudo_perm.comment + else: + asset_group_permed = [] + cmd_group_permed = [] + + asset_groups = [asset_group for asset_group in asset_group_all if asset_group not in asset_group_permed] + cmd_groups = [cmd_group for cmd_group in cmd_group_all if cmd_group not in cmd_group_permed] + + else: + user_group_id = request.POST.get('user_group_id', '') + users_runas = request.POST.get('runas', 'root') + asset_groups_select = request.POST.getlist('asset_groups_select') + cmd_groups_select = request.POST.getlist('cmd_groups_select') + comment = request.POST.get('comment', '') + user_group = UserGroup.objects.filter(id=user_group_id) + if not validate(request, user_group=[user_group_id], asset_group=asset_groups_select): + return render_to_response('/jperm/sudo_list/') + if user_group: + user_group = user_group[0] + if LDAP_ENABLE: + sudo_update(user_group, users_runas, asset_groups_select, cmd_groups_select, comment) + msg = '修改成功' + + return HttpResponseRedirect('/jperm/sudo_list/') + return render_to_response('jperm/sudo_edit.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def sudo_detail(request): + header_title, path1, path2 = u'Sudo授权详情', u'授权管理', u'授权详情' + user_group_id = request.GET.get('id') + user_group = UserGroup.objects.filter(id=user_group_id) + if user_group: + asset_groups = [] + cmd_groups = [] + user_group = user_group[0] + users = user_group.user_set.all() + group_user_num = len(users) + + for perm in user_group.sudoperm_set.all(): + asset_groups.extend(perm.asset_group.all()) + cmd_groups.extend(perm.cmd_group.all()) + + print asset_groups + return render_to_response('jperm/sudo_detail.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def sudo_refresh(request): + sudo_perm_all = SudoPerm.objects.all() + for sudo_perm in sudo_perm_all: + user_group = sudo_perm.user_group + user_runas = sudo_perm.user_runas + asset_groups_select = sudo_perm.asset_group.all() + cmd_groups_select = sudo_perm.cmd_group.all() + sudo_ldap_add(user_group, user_runas, asset_groups_select, cmd_groups_select) + return HttpResponse('刷新sudo授权成功') + + +@require_super_user +def cmd_add(request): + header_title, path1, path2 = u'sudo命令添加', u'授权管理', u'命令组添加' + dept_all = DEPT.objects.all() + + if request.method == 'POST': + name = request.POST.get('name') + dept_id = request.POST.get('dept_id') + cmd = ','.join(request.POST.get('cmd').split()) + comment = request.POST.get('comment') + dept = DEPT.objects.filter(id=dept_id) + + try: + if CmdGroup.objects.filter(name=name): + error = '%s 命令组已存在' + raise ServerError(error) + + if not dept: + error = u"部门不能为空" + raise ServerError(error) + except ServerError, e: + pass + else: + dept = dept[0] + CmdGroup.objects.create(name=name, dept=dept, cmd=cmd, comment=comment) + msg = u'命令组添加成功' + return HttpResponseRedirect('/jperm/cmd_list/') + + return render_to_response('jperm/sudo_cmd_add.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def cmd_add_adm(request): + header_title, path1, path2 = u'sudo命令添加', u'授权管理', u'命令组添加' + user, dept = get_session_user_dept(request) + + if request.method == 'POST': + name = request.POST.get('name') + cmd = ','.join(request.POST.get('cmd').split()) + comment = request.POST.get('comment') + + try: + if CmdGroup.objects.filter(name=name): + error = '%s 命令组已存在' + raise ServerError(error) + except ServerError, e: + pass + else: + CmdGroup.objects.create(name=name, dept=dept, cmd=cmd, comment=comment) + return HttpResponseRedirect('/jperm/cmd_list/') + + return HttpResponseRedirect('/jperm/cmd_list/') + + return render_to_response('jperm/sudo_cmd_add.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def cmd_edit(request): + header_title, path1, path2 = u'sudo命令修改', u'授权管理管理', u'命令组修改' + + cmd_group_id = request.GET.get('id') + cmd_group = CmdGroup.objects.filter(id=cmd_group_id) + dept_all = DEPT.objects.all() + + if cmd_group: + cmd_group = cmd_group[0] + cmd_group_id = cmd_group.id + dept_id = cmd_group.dept.id + name = cmd_group.name + cmd = '\n'.join(cmd_group.cmd.split(',')) + comment = cmd_group.comment + + if request.method == 'POST': + cmd_group_id = request.POST.get('cmd_group_id') + name = request.POST.get('name') + dept_id = request.POST.get('dept_id') + cmd = ','.join(request.POST.get('cmd').split()) + comment = request.POST.get('comment') + cmd_group = CmdGroup.objects.filter(id=cmd_group_id) + + dept = DEPT.objects.filter(id=dept_id) + try: + if not dept: + error = '没有该部门' + raise ServerError(error) + + if not cmd_group: + error = '没有该命令组' + except ServerError, e: + pass + else: + cmd_group.update(name=name, cmd=cmd, dept=dept[0], comment=comment) + return HttpResponseRedirect('/jperm/cmd_list/') + return render_to_response('jperm/sudo_cmd_add.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def cmd_list(request): + header_title, path1, path2 = u'sudo命令查看', u'权限管理', u'Sudo命令添加' + + if is_super_user(request): + cmd_groups = contact_list = CmdGroup.objects.all() + else: + user, dept = get_session_user_dept(request) + cmd_groups = contact_list = dept.cmdgroup_set.all() + p = paginator = Paginator(contact_list, 10) + + try: + page = int(request.GET.get('page', '1')) + except ValueError: + page = 1 + + try: + contacts = paginator.page(page) + except (EmptyPage, InvalidPage): + contacts = paginator.page(paginator.num_pages) + return render_to_response('jperm/sudo_cmd_list.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def cmd_del(request): + cmd_group_id = request.GET.get('id') + cmd_group = CmdGroup.objects.filter(id=cmd_group_id) + + if cmd_group: + cmd_group[0].delete() + return HttpResponseRedirect('/jperm/cmd_list/') + + +@require_admin +def cmd_detail(request): + cmd_ids = request.GET.get('id').split(',') + cmds = [] + if len(cmd_ids) == 1: + if cmd_ids[0]: + cmd_id = cmd_ids[0] + else: + cmd_id = 1 + cmd_group = CmdGroup.objects.filter(id=cmd_id) + if cmd_group: + cmd_group = cmd_group[0] + cmds.extend(cmd_group.cmd.split(',')) + cmd_group_name = cmd_group.name + else: + cmd_groups = [] + for cmd_id in cmd_ids: + cmd_groups.extend(CmdGroup.objects.filter(id=cmd_id)) + for cmd_group in cmd_groups: + cmds.extend(cmd_group.cmd.split(',')) + + cmds_str = ', '.join(cmds) + + return render_to_response('jperm/sudo_cmd_detail.html', locals(), context_instance=RequestContext(request)) + + +@require_login +def perm_apply(request): + """ 权限申请 """ + header_title, path1, path2 = u'主机权限申请', u'权限管理', u'申请主机' + user_id, username = get_session_user_info(request)[0:2] + name = User.objects.get(id=user_id).name + dept_id, deptname, dept = get_session_user_info(request)[3:6] + perm_host = user_perm_asset_api(username) + all_host = Asset.objects.filter(dept=dept) + + perm_group = user_perm_group_api(username) + all_group = dept.bisgroup_set.all() + + posts = [g for g in all_host if g not in perm_host] + egroup = [d for d in all_group if d not in perm_group] + + dept_da = User.objects.filter(dept_id=dept_id, role='DA') + admin = User.objects.get(name='admin') + + if request.method == 'POST': + applyer = request.POST.get('applyer') + dept = request.POST.get('dept') + da = request.POST.get('da') + group = request.POST.getlist('group') + hosts = request.POST.getlist('hosts') + comment = request.POST.get('comment') + if not da: + return httperror(request, u'请选择管理员!') + da = User.objects.get(id=da) + mail_address = da.email + mail_title = '%s - 权限申请' % username + group_lis = ', '.join(group) + hosts_lis = ', '.join(hosts) + time_now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + a = Apply.objects.create(applyer=applyer, admin=da, dept=dept, bisgroup=group, date_add=datetime.datetime.now(), + asset=hosts, status=0, comment=comment, read=0) + uuid = a.uuid + url = "http://%s:%s/jperm/apply_exec/?uuid=%s" % (SEND_IP, SEND_PORT, uuid) + mail_msg = """ + Hi,%s: + 有新的权限申请, 详情如下: + 申请人: %s + 申请主机组: %s + 申请的主机: %s + 申请时间: %s + 申请说明: %s + 请及时审批, 审批完成后, 点击以下链接或登录授权管理-权限审批页面点击确认键,告知申请人。 + + %s + """ % (da.username, applyer, group_lis, hosts_lis, time_now, comment, url) + + send_mail(mail_title, mail_msg, MAIL_FROM, [mail_address], fail_silently=False) + smg = "提交成功,已发邮件至 %s 通知部门管理员。" % mail_address + return render_to_response('jperm/perm_apply.html', locals(), context_instance=RequestContext(request)) + return render_to_response('jperm/perm_apply.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def perm_apply_exec(request): + """ 确认权限 """ + header_title, path1, path2 = u'主机权限申请', u'权限管理', u'审批完成' + uuid = request.GET.get('uuid') + user_id = request.session.get('user_id') + approver = User.objects.get(id=user_id).name + if uuid: + p_apply = Apply.objects.filter(uuid=str(uuid)) + q_apply = Apply.objects.get(uuid=str(uuid)) + if q_apply.status == 1: + smg = '此权限已经审批完成, 请勿重复审批, 十秒钟后返回首页' + return render_to_response('jperm/perm_apply_exec.html', locals(), context_instance=RequestContext(request)) + else: + user = User.objects.get(username=q_apply.applyer) + mail_address = user.email + time_now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + p_apply.update(status=1, approver=approver, date_end=time_now) + mail_title = '%s - 权限审批完成' % q_apply.applyer + mail_msg = """ + Hi,%s: + 您所申请的权限已由 %s 在 %s 审批完成, 请登录验证。 + """ % (q_apply.applyer, q_apply.approver, time_now) + send_mail(mail_title, mail_msg, MAIL_FROM, [mail_address], fail_silently=False) + smg = '授权完成, 已邮件通知申请人, 十秒钟后返回首页' + return render_to_response('jperm/perm_apply_exec.html', locals(), context_instance=RequestContext(request)) + else: + smg = '没有此授权记录, 十秒钟后返回首页' + return render_to_response('jperm/perm_apply_exec.html', locals(), context_instance=RequestContext(request)) + + +def get_apply_posts(request, status, username, dept_name, keyword=None): + """ 获取申请记录 """ + post_all = Apply.objects.filter(status=status).order_by('-date_add') + post_keyword_all = Apply.objects.filter(Q(applyer__contains=keyword) | + Q(approver__contains=keyword)) \ + .filter(status=status).order_by('-date_add') + + if is_super_user(request): + if keyword: + posts = post_keyword_all + else: + posts = post_all + elif is_group_admin(request): + if keyword: + posts = post_keyword_all.filter(dept=dept_name) + else: + posts = post_all.filter(dept=dept_name) + elif is_common_user(request): + if keyword: + posts = post_keyword_all.filter(applyer=username) + else: + posts = post_all.filter(applyer=username) + + return posts + + +@require_login +def perm_apply_log(request, offset): + """ 申请记录 """ + header_title, path1, path2 = u'权限申请记录', u'权限管理', u'申请记录' + keyword = request.GET.get('keyword', '') + user_id = get_session_user_info(request)[0] + username = User.objects.get(id=user_id).name + dept_name = get_session_user_info(request)[4] + status_dic = {'online': 0, 'offline': 1} + status = status_dic[offset] + posts = get_apply_posts(request, status, username, dept_name, keyword) + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) + return render_to_response('jperm/perm_log_%s.html' % offset, locals(), context_instance=RequestContext(request)) + + +@require_login +def perm_apply_info(request): + """ 申请信息详情 """ + uuid = request.GET.get('uuid', '') + post = Apply.objects.filter(uuid=uuid) + username = get_session_user_info(request)[1] + if post: + post = post[0] + if post.read == 0 and post.applyer != username: + post.read = 1 + post.save() + else: + return httperror(request, u'没有这个申请记录!') + + return render_to_response('jperm/perm_apply_info.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def perm_apply_del(request): + """ 删除日志记录 """ + uuid = request.GET.get('uuid') + u_apply = Apply.objects.filter(uuid=uuid) + if u_apply: + u_apply.delete() + return HttpResponseRedirect('/jperm/apply_show/online/') + + +@require_login +def perm_apply_search(request): + """ 申请搜索 """ + keyword = request.GET.get('keyword') + offset = request.GET.get('env') + username = get_session_user_info(request)[1] + dept_name = get_session_user_info(request)[3] + status_dic = {'online': 0, 'offline': 1} + status = status_dic[offset] + posts = get_apply_posts(request, status, username, dept_name, keyword) + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(posts, request) + return render_to_response('jperm/perm_apply_search.html', locals(), context_instance=RequestContext(request)) + + + + + + + + + + + + + + diff --git a/jumpserver.conf b/jumpserver.conf index 4f0913527cdb..c1e035757059 100644 --- a/jumpserver.conf +++ b/jumpserver.conf @@ -1,16 +1,34 @@ -#coding:utf-8 +#coding: utf8 + +[base] +ip = 192.168.20.209 +port = 80 +key = 88aaaf7ffe3c6c04 + [db] host = 127.0.0.1 port = 3306 -user = root -password = redhat -db = jumpserver +user = jumpserver +password = mysql234 +database = jumpserver -[jumpserver] -key = 88aaaf7ffe3c6c04 -ldap_host = ldap://127.0.0.1:389 -ldap_base_dn = dc=yolu,dc=com -admin_cn = cn=admin,dc=yolu,dc=com -admin_pass = VNLqNCjpNBIetEoCA2h3 -web_socket_host = 172.10.10.9:3000 \ No newline at end of file + +[ldap] +ldap_enable = 1 +host_url = ldap://127.0.0.1:389 +base_dn = dc=jumpserver, dc=org +root_dn = cn=admin,dc=jumpserver,dc=org +root_pw = secret234 + + +[websocket] +web_socket_host = 192.168.20.209:3000 + + +[mail] +email_host = smtp.exmail.qq.com +email_port = 25 +email_host_user = noreply@jumpserver.org +email_host_password = jumpserver123 +email_use_tls = False diff --git a/jumpserver.py b/jumpserver.py deleted file mode 100755 index 12f466b2a966..000000000000 --- a/jumpserver.py +++ /dev/null @@ -1,311 +0,0 @@ -#!/usr/bin/python -# coding: utf-8 - - -import os -import sys -import subprocess -import struct -import fcntl -import termios -import signal -import re -import time -from Crypto.Cipher import AES -from binascii import b2a_hex, a2b_hex -import ConfigParser -import paramiko -import pxssh -import pexpect -import readline - -cur_dir = os.path.abspath(os.path.dirname(__file__)) -sys.path.append('%s/webroot/AutoSa/' % cur_dir) -os.environ['DJANGO_SETTINGS_MODULE'] = 'AutoSa.settings' - -import django -django.setup() -from UserManage.models import User, Logs, Pid -from Assets.models import Assets - - -cf = ConfigParser.ConfigParser() -cf.read('%s/jumpserver.conf' % cur_dir) - -db_host = cf.get('db', 'host') -db_port = cf.getint('db', 'port') -db_user = cf.get('db', 'user') -db_password = cf.get('db', 'password') -db_db = cf.get('db', 'db') -log_dir = os.path.join(cur_dir, 'logs') -key = cf.get('jumpserver', 'key') - - -class PyCrypt(object): - """It's used to encrypt and decrypt password.""" - def __init__(self, key): - self.key = key - self.mode = AES.MODE_CBC - - def encrypt(self, text): - cryptor = AES.new(self.key, self.mode, b'0000000000000000') - length = 16 - count = len(text) - if count < length: - add = (length - count) - text += ('\0' * add) - elif count > length: - add = (length - (count % length)) - text += ('\0' * add) - ciphertext = cryptor.encrypt(text) - return b2a_hex(ciphertext) - - def decrypt(self, text): - cryptor = AES.new(self.key, self.mode, b'0000000000000000') - plain_text = cryptor.decrypt(a2b_hex(text)) - return plain_text.rstrip('\0') - - -def sigwinch_passthrough(sig, data): - """This function use to set the window size of the terminal!""" - winsize = getwinsize() - try: - foo.setwinsize(winsize[0], winsize[1]) - except: - pass - - -def getwinsize(): - """This function use to get the size of the windows!""" - if 'TIOCGWINSZ' in dir(termios): - TIOCGWINSZ = termios.TIOCGWINSZ - else: - TIOCGWINSZ = 1074295912L # Assume - s = struct.pack('HHHH', 0, 0, 0, 0) - x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s) - return struct.unpack('HHHH', x)[0:2] - - -def run_cmd(cmd): - """run command and return stdout""" - pipe = subprocess.Popen(cmd, - shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - if pipe.stdout: - stdout = pipe.stdout.read().strip() - pipe.wait() - return stdout - if pipe.stderr: - stderr = pipe.stderr.read() - pipe.wait() - return stderr - - -def connect(host, port, user, password): - """Use pexpect module to connect other server.""" - log_date_dir = '%s/%s' % (log_dir, time.strftime('%Y%m%d')) - if not os.path.isdir(log_date_dir): - os.mkdir(log_date_dir) - os.chmod(log_date_dir, 0777) - structtime_start = time.localtime() - datetime_start = time.strftime('%Y%m%d%H%M%S', structtime_start) - logtime_start = time.strftime('%Y/%m/%d %H:%M:%S', structtime_start) - timestamp_start = int(time.mktime(structtime_start)) - logfile_name = "%s/%s_%s_%s" % (log_date_dir, host, user, datetime_start) - - try: - global foo - foo = pxssh.pxssh() - foo.login(host, user, password, port=port, auto_prompt_reset=False) - log = Logs(user=user, host=host, logfile=logfile_name, start_time=timestamp_start, ppid=os.getpid()) # 日志信息记录到数据库 - log.save() - pid = Pid(ppid=os.getpid(), cpid=foo.pid, start_time=timestamp_start, logid=log.id) - pid.save() - - logfile = open(logfile_name, 'a') # 记录日志文件 - logfile.write('\nDateTime:%s' % logtime_start) - foo.logfile = logfile - foo.sendline("export PS1='[\u@%s \W]\$ ';clear" % host) - signal.signal(signal.SIGWINCH, sigwinch_passthrough) - size = getwinsize() - foo.setwinsize(size[0], size[1]) - foo.interact(escape_character=chr(28)) # 进入交互模式 - logfile.write('\nEndTime: %s' % time.strftime('%Y/%m/%d %H:%M:%S')) - log.finish = 1 - log.end_time = int(time.time()) - log.save() - - except pxssh.ExceptionPxssh as e: - print('登录失败: %s' % e) - except pexpect.EOF: - print('登录失败: Host refuse') - except KeyboardInterrupt: - foo.logout() - log.finish = 1 - log.end_time = int(time.time()) - log.save() - - -def ip_all_select(username): - """select all the server of the user can control.""" - ip_all = [] - ip_all_dict = {} - try: - user = User.objects.get(username=username) - except: - return (['error'], {'error':"Don't Use Root To Do That or User isn't Exist."}) - all_assets_user = user.assetsuser_set.all() - for assets_user in all_assets_user: - ip_all.append(assets_user.aid.ip) - ip_all_dict[assets_user.aid.ip] = assets_user.aid.comment - - return ip_all, ip_all_dict - - -def sth_select(username='', ip=''): - """if username: return password elif ip return port""" - if username: - user = User.objects.get(username=username) - ldap_password = user.ldap_password - return ldap_password - - if ip: - asset = Assets.objects.get(ip=ip) - port = asset.port - return port - return None - - -def remote_exec_cmd(host, user, cmd): - jm = PyCrypt(key) - ssh = paramiko.SSHClient() - ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - port = sth_select(ip=host) - password = jm.decrypt(sth_select(username=username)) - try: - ssh.connect(host, port, user, password) - except paramiko.AuthenticationException: - print 'Password Error .' - return None - stdin, stdout, stderr = ssh.exec_command(cmd) - print '\033[32m' + '#'*15 + ' ' + host + ' ' + '#'*15 + '\n' + '\033[0m' - output = stdout.read() - error = stderr.read() - if output: - print output - if error: - print error - print '\033[32m' + '#'*15 + ' End result ' + '#'*15 + '\n' + '\033[0m' - ssh.close() - - -def match_ip(all_ip, string): - ip_matched = [] - pattern = re.compile(r'%s' % string) - - for ip in all_ip: - if pattern.search(ip): - ip_matched.append(ip) - return ip_matched - - -def print_prompt(): - print """ -\033[1;32m### Welcome Use JumpServer To Login. ### \033[0m -1) Type \033[32mIP ADDRESS\033[0m To Login. -2) Type \033[32mP/p\033[0m To Print The Servers You Available. -3) Type \033[32mE/e\033[0m To Execute Command On Several Servers. -4) Type \033[32mQ/q\033[0m To Quit. -""" - - -def print_your_server(username): - ip_all, ip_all_dict = ip_all_select(username) - for ip in ip_all: - if ip_all_dict[ip]: - print "%s -- %s" % (ip, ip_all_dict[ip]) - else: - print ip - - -def exec_cmd_servers(username): - print '\nInput the \033[32mHost IP(s)\033[0m,Separated by Commas, q/Q to Quit.\n' - while True: - hosts = raw_input('\033[1;32mip(s)>: \033[0m') - if hosts in ['q', 'Q']: - break - hosts = hosts.split(',') - hosts.append('') - hosts = list(set(hosts)) - hosts.remove('') - ip_all, ip_all_dict = ip_all_select(username) - no_perm = set(hosts)-set(ip_all) - if no_perm: - print "You have NO PERMISSION on %s..." % list(no_perm) - continue - print '\nInput the \033[32mCommand\033[0m , The command will be Execute on servers, q/Q to quit.\n' - while True: - cmd = raw_input('\033[1;32mCmd(s): \033[0m') - if cmd in ['q', 'Q']: - break - exec_log_dir = os.path.join(log_dir, 'exec_cmds') - if not os.path.isdir(exec_log_dir): - os.mkdir(exec_log_dir) - os.chmod(exec_log_dir, 0777) - filename = "%s/%s.log" % (exec_log_dir, time.strftime('%Y%m%d')) - f = open(filename, 'a') - f.write("DateTime: %s User: %s Host: %s Cmds: %s\n" % - (time.strftime('%Y/%m/%d %H:%M:%S'), username, hosts, cmd)) - for host in hosts: - remote_exec_cmd(host, username, cmd) - - -def connect_one(username, option): - ip_input = option.strip() - ip_all, ip_all_dict = ip_all_select(username) - ip_matched = match_ip(ip_all, ip_input) - ip_len = len(ip_matched) - ip = '' - if ip_len >= 1: - if ip_len == 1: - ip = ip_matched[0] - else: - if ip_input in ip_matched: - ip = ip_input - else: - for one_ip in ip_matched: - print one_ip - if ip: - password = jm.decrypt(sth_select(username=username)) - port = sth_select(ip=ip) - print "Connecting %s ..." % ip - connect(ip, port, username, password) - else: - print '\033[31mNo permision .\033[0m' - - -if __name__ == '__main__': - username = run_cmd('whoami') - jm = PyCrypt(key) - print_prompt() - try: - while True: - try: - option = raw_input("\033[1;32mOpt or IP>:\033[0m ") - except EOFError: - print - continue - if option in ['P', 'p']: - print_your_server(username) - continue - elif option in ['e', 'E']: - exec_cmd_servers(username) - elif option in ['q', 'Q']: - sys.exit() - else: - connect_one(username, option) - #except (BaseException, Exception): - except IndexError: - print "Exit." - sys.exit() diff --git a/webroot/AutoSa/UserManage/__init__.py b/jumpserver/__init__.py similarity index 100% rename from webroot/AutoSa/UserManage/__init__.py rename to jumpserver/__init__.py diff --git a/jumpserver/api.py b/jumpserver/api.py new file mode 100644 index 000000000000..7c416925ad5c --- /dev/null +++ b/jumpserver/api.py @@ -0,0 +1,502 @@ +# coding: utf-8 + + +from django.http import HttpResponseRedirect +import json +import os +from ConfigParser import ConfigParser +import getpass +from Crypto.Cipher import AES +from binascii import b2a_hex, a2b_hex +import ldap +from ldap import modlist +import hashlib +import datetime +import subprocess +from django.core.paginator import Paginator, EmptyPage, InvalidPage +from django.http import HttpResponse, Http404 +from django.shortcuts import render_to_response +from juser.models import User, UserGroup, DEPT +from jasset.models import Asset, BisGroup, IDC +from jlog.models import Log +from jasset.models import AssetAlias +from django.core.exceptions import ObjectDoesNotExist +from django.core.mail import send_mail + + +BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) +CONF = ConfigParser() +CONF.read(os.path.join(BASE_DIR, 'jumpserver.conf')) +LOG_DIR = os.path.join(BASE_DIR, 'logs') +SSH_KEY_DIR = os.path.join(BASE_DIR, 'keys') +SERVER_KEY_DIR = os.path.join(SSH_KEY_DIR, 'server') +KEY = CONF.get('base', 'key') +LOGIN_NAME = getpass.getuser() +LDAP_ENABLE = CONF.getint('ldap', 'ldap_enable') +SEND_IP = CONF.get('base', 'ip') +SEND_PORT = CONF.get('base', 'port') +MAIL_FROM = CONF.get('mail', 'email_host_user') + + +class LDAPMgmt(): + def __init__(self, + host_url, + base_dn, + root_cn, + root_pw): + self.ldap_host = host_url + self.ldap_base_dn = base_dn + self.conn = ldap.initialize(host_url) + self.conn.set_option(ldap.OPT_REFERRALS, 0) + self.conn.protocol_version = ldap.VERSION3 + self.conn.simple_bind_s(root_cn, root_pw) + + def list(self, filter, scope=ldap.SCOPE_SUBTREE, attr=None): + result = {} + try: + ldap_result = self.conn.search_s(self.ldap_base_dn, scope, filter, attr) + for entry in ldap_result: + name, data = entry + for k, v in data.items(): + print '%s: %s' % (k, v) + result[k] = v + return result + except ldap.LDAPError, e: + print e + + def add(self, dn, attrs): + try: + ldif = modlist.addModlist(attrs) + self.conn.add_s(dn, ldif) + except ldap.LDAPError, e: + print e + + def modify(self, dn, attrs): + try: + attr_s = [] + for k, v in attrs.items(): + attr_s.append((2, k, v)) + self.conn.modify_s(dn, attr_s) + except ldap.LDAPError, e: + print e + + def delete(self, dn): + try: + self.conn.delete_s(dn) + except ldap.LDAPError, e: + print e + + def decrypt(self, text): + cryptor = AES.new(self.key, self.mode, b'0000000000000000') + try: + plain_text = cryptor.decrypt(a2b_hex(text)) + except TypeError: + raise ServerError('Decrypt password error, TYpe error.') + return plain_text.rstrip('\0') + + +if LDAP_ENABLE: + LDAP_HOST_URL = CONF.get('ldap', 'host_url') + LDAP_BASE_DN = CONF.get('ldap', 'base_dn') + LDAP_ROOT_DN = CONF.get('ldap', 'root_dn') + LDAP_ROOT_PW = CONF.get('ldap', 'root_pw') + ldap_conn = LDAPMgmt(LDAP_HOST_URL, LDAP_BASE_DN, LDAP_ROOT_DN, LDAP_ROOT_PW) +else: + ldap_conn = None + + +def md5_crypt(string): + return hashlib.new("md5", string).hexdigest() + + +def page_list_return(total, current=1): + min_page = current - 2 if current - 4 > 0 else 1 + max_page = min_page + 4 if min_page + 4 < total else total + + return range(min_page, max_page+1) + + +def pages(posts, r): + """分页公用函数""" + contact_list = posts + p = paginator = Paginator(contact_list, 10) + try: + current_page = int(r.GET.get('page', '1')) + except ValueError: + current_page = 1 + + page_range = page_list_return(len(p.page_range), current_page) + + try: + contacts = paginator.page(current_page) + except (EmptyPage, InvalidPage): + contacts = paginator.page(paginator.num_pages) + + if current_page >= 5: + show_first = 1 + else: + show_first = 0 + if current_page <= (len(p.page_range) - 3): + show_end = 1 + else: + show_end = 0 + + return contact_list, p, contacts, page_range, current_page, show_first, show_end + + +class PyCrypt(object): + """This class used to encrypt and decrypt password.""" + + def __init__(self, key): + self.key = key + self.mode = AES.MODE_CBC + + def encrypt(self, text): + cryptor = AES.new(self.key, self.mode, b'0000000000000000') + length = 16 + try: + count = len(text) + except TypeError: + raise ServerError('Encrypt password error, TYpe error.') + add = (length - (count % length)) + text += ('\0' * add) + ciphertext = cryptor.encrypt(text) + return b2a_hex(ciphertext) + + def decrypt(self, text): + cryptor = AES.new(self.key, self.mode, b'0000000000000000') + try: + plain_text = cryptor.decrypt(a2b_hex(text)) + except TypeError: + raise ServerError('Decrypt password error, TYpe error.') + return plain_text.rstrip('\0') + + +CRYPTOR = PyCrypt(KEY) + + +class ServerError(Exception): + pass + + +def get_object(model, **kwargs): + try: + the_object = model.objects.get(**kwargs) + except ObjectDoesNotExist: + raise ServerError('Object get %s failed.' % str(kwargs.values())) + return the_object + + +def require_login(func): + """要求登录的装饰器""" + def _deco(request, *args, **kwargs): + if not request.session.get('user_id'): + return HttpResponseRedirect('/login/') + return func(request, *args, **kwargs) + return _deco + + +def require_super_user(func): + def _deco(request, *args, **kwargs): + if not request.session.get('user_id'): + return HttpResponseRedirect('/login/') + + if request.session.get('role_id', 0) != 2: + return HttpResponseRedirect('/') + return func(request, *args, **kwargs) + return _deco + + +def require_admin(func): + def _deco(request, *args, **kwargs): + if not request.session.get('user_id'): + return HttpResponseRedirect('/login/') + + if request.session.get('role_id', 0) < 1: + return HttpResponseRedirect('/') + return func(request, *args, **kwargs) + return _deco + + +def is_super_user(request): + if request.session.get('role_id') == 2: + return True + else: + return False + + +def is_group_admin(request): + if request.session.get('role_id') == 1: + return True + else: + return False + + +def is_common_user(request): + if request.session.get('role_id') == 0: + return True + else: + return False + + +@require_login +def get_session_user_dept(request): + user_id = request.session.get('user_id', 0) + user = User.objects.filter(id=user_id) + if user: + user = user[0] + dept = user.dept + return user, dept + + +@require_login +def get_session_user_info(request): + user_id = request.session.get('user_id', 0) + user = User.objects.filter(id=user_id) + if user: + user = user.first() + dept = user.dept + return [user.id, user.username, user, dept.id, dept.name, dept] + + +def get_user_dept(request): + user_id = request.session.get('user_id') + if user_id: + user_dept = User.objects.get(id=user_id).dept + return user_dept.id + + +def api_user(request): + hosts = Log.objects.filter(is_finished=0).count() + users = Log.objects.filter(is_finished=0).values('user').distinct().count() + ret = {'users': users, 'hosts': hosts} + json_data = json.dumps(ret) + return HttpResponse(json_data) + + +def view_splitter(request, su=None, adm=None): + if is_super_user(request): + return su(request) + elif is_group_admin(request): + return adm(request) + else: + return HttpResponseRedirect('/login/') + + +def user_group_perm_asset_group_api(user_group): + asset_group_list = [] + perm_list = user_group.perm_set.all() + for perm in perm_list: + asset_group_list.append(perm.asset_group) + return asset_group_list + + +def user_perm_group_api(username): + if username: + user = User.objects.get(username=username) + perm_list = [] + user_group_all = user.group.all() + for user_group in user_group_all: + perm_list.extend(user_group.perm_set.all()) + + asset_group_list = [] + for perm in perm_list: + asset_group_list.append(perm.asset_group) + return asset_group_list + + +def user_perm_group_hosts_api(gid): + hostgroup = BisGroup.objects.filter(id=gid) + if hostgroup: + return hostgroup[0].asset_set.all() + else: + return [] + + +def user_perm_asset_api(username): + user = User.objects.filter(username=username) + if user: + user = user[0] + asset_list = [] + asset_group_list = user_perm_group_api(user) + for asset_group in asset_group_list: + asset_list.extend(asset_group.asset_set.all()) + asset_list = list(set(asset_list)) + return asset_list + else: + return [] + + +def asset_perm_api(asset): + if asset: + perm_list = [] + asset_group_all = asset.bis_group.all() + for asset_group in asset_group_all: + perm_list.extend(asset_group.perm_set.all()) + + user_group_list = [] + for perm in perm_list: + user_group_list.append(perm.user_group) + + user_permed_list = [] + for user_group in user_group_list: + user_permed_list.extend(user_group.user_set.all()) + user_permed_list = list(set(user_permed_list)) + return user_permed_list + + +def get_user_host(username): + """Get the hosts of under the user control.""" + hosts_attr = {} + asset_all = user_perm_asset_api(username) + user = User.objects.filter(username=username) + if user: + user = user[0] + for asset in asset_all: + alias = AssetAlias.objects.filter(user=user, host=asset) + if alias and alias[0].alias != '': + hosts_attr[asset.ip] = [asset.id, asset.ip, alias[0].alias] + else: + hosts_attr[asset.ip] = [asset.id, asset.ip, asset.comment] + return hosts_attr + else: + raise ServerError('User %s does not exit!' % username) + + +def get_connect_item(username, ip): + asset = get_object(Asset, ip=ip) + port = asset.port + + if not asset.is_active: + raise ServerError('Host %s is not active.' % ip) + + user = get_object(User, username=username) + + if not user.is_active: + raise ServerError('User %s is not active.' % username) + + login_type_dict = { + 'L': user.ldap_pwd, + } + + if asset.login_type in login_type_dict: + password = CRYPTOR.decrypt(login_type_dict[asset.login_type]) + return username, password, ip, port + + elif asset.login_type == 'M': + username = asset.username + password = CRYPTOR.decrypt(asset.password) + return username, password, ip, port + + else: + raise ServerError('Login type is not in ["L", "M"]') + + +def validate(request, user_group=None, user=None, asset_group=None, asset=None, edept=None): + dept = get_session_user_dept(request)[1] + if edept: + if dept.id != int(edept[0]): + return False + + if user_group: + dept_user_groups = dept.usergroup_set.all() + user_group_ids = [] + for group in dept_user_groups: + user_group_ids.append(str(group.id)) + + if not set(user_group).issubset(set(user_group_ids)): + return False + + if user: + dept_users = dept.user_set.all() + user_ids = [] + for dept_user in dept_users: + user_ids.append(str(dept_user.id)) + + if not set(user).issubset(set(user_ids)): + return False + + if asset_group: + dept_asset_groups = dept.bisgroup_set.all() + asset_group_ids = [] + for group in dept_asset_groups: + asset_group_ids.append(str(group.id)) + + if not set(asset_group).issubset(set(asset_group_ids)): + return False + + if asset: + dept_assets = dept.asset_set.all() + asset_ids = [] + for dept_asset in dept_assets: + asset_ids.append(str(dept_asset.id)) + + if not set(asset).issubset(set(asset_ids)): + return False + + return True + + +def verify(request, user_group=None, user=None, asset_group=None, asset=None, edept=None): + dept = get_session_user_dept(request)[1] + if edept: + if dept.id != int(edept[0]): + return False + + if user_group: + dept_user_groups = dept.usergroup_set.all() + user_groups = [] + for user_group_id in user_group: + user_groups.extend(UserGroup.objects.filter(id=user_group_id)) + if not set(user_groups).issubset(set(dept_user_groups)): + return False + + if user: + dept_users = dept.user_set.all() + users = [] + for user_id in user: + users.extend(User.objects.filter(id=user_id)) + + if not set(users).issubset(set(dept_users)): + return False + + if asset_group: + dept_asset_groups = dept.bisgroup_set.all() + asset_group_ids = [] + for group in dept_asset_groups: + asset_group_ids.append(str(group.id)) + + if not set(asset_group).issubset(set(asset_group_ids)): + return False + + if asset: + dept_assets = dept.asset_set.all() + asset_ids = [] + for a in dept_assets: + asset_ids.append(str(a.id)) + print asset, asset_ids + if not set(asset).issubset(set(asset_ids)): + return False + + return True + + +def bash(cmd): + """执行bash命令""" + return subprocess.call(cmd, shell=True) + + +def is_dir(dir_name, username='root', mode=0755): + if not os.path.isdir(dir_name): + os.makedirs(dir_name) + bash("chown %s:%s '%s'" % (username, username, dir_name)) + os.chmod(dir_name, mode) + + +def success(request, msg): + return render_to_response('success.html', locals()) + + +def httperror(request, emg): + message = emg + return render_to_response('error.html', locals()) \ No newline at end of file diff --git a/jumpserver/context_processors.py b/jumpserver/context_processors.py new file mode 100644 index 000000000000..aac09c7a7418 --- /dev/null +++ b/jumpserver/context_processors.py @@ -0,0 +1,35 @@ +from juser.models import User +from jasset.models import Asset +from jumpserver.api import * +from jperm.models import Apply + + +def name_proc(request): + user_id = request.session.get('user_id') + role_id = request.session.get('role_id') + if role_id == 2: + user_total_num = User.objects.all().count() + user_active_num = User.objects.filter().count() + host_total_num = Asset.objects.all().count() + host_active_num = Asset.objects.filter(is_active=True).count() + else: + user, dept = get_session_user_dept(request) + user_total_num = dept.user_set.all().count() + user_active_num = dept.user_set.filter(is_active=True).count() + host_total_num = dept.asset_set.all().count() + host_active_num = dept.asset_set.all().filter(is_active=True).count() + + username = User.objects.get(id=user_id).name + apply_info = Apply.objects.filter(admin=username, status=0, read=0) + request.session.set_expiry(3600) + + info_dic = {'session_user_id': user_id, + 'session_role_id': role_id, + 'user_total_num': user_total_num, + 'user_active_num': user_active_num, + 'host_total_num': host_total_num, + 'host_active_num': host_active_num, + 'apply_info': apply_info} + + return info_dic + diff --git a/webroot/AutoSa/AutoSa/settings.py b/jumpserver/settings.py similarity index 58% rename from webroot/AutoSa/AutoSa/settings.py rename to jumpserver/settings.py index cbd7561f6b2c..d44a781ee134 100644 --- a/webroot/AutoSa/AutoSa/settings.py +++ b/jumpserver/settings.py @@ -1,40 +1,47 @@ """ -Django settings for AutoSa project. +Django settings for jumpserver project. For more information on this file, see -https://docs.djangoproject.com/en/1.6/topics/settings/ +https://docs.djangoproject.com/en/1.7/topics/settings/ For the full list of settings and their values, see -https://docs.djangoproject.com/en/1.6/ref/settings/ +https://docs.djangoproject.com/en/1.7/ref/settings/ """ # Build paths inside the project like this: os.path.join(BASE_DIR, ...) import os import ConfigParser +config = ConfigParser.ConfigParser() + BASE_DIR = os.path.dirname(os.path.dirname(__file__)) -CONF_DIR = os.path.dirname(os.path.dirname(BASE_DIR)) -CF = ConfigParser.ConfigParser() -CF.read('%s/jumpserver.conf' % CONF_DIR) +config.read(os.path.join(BASE_DIR, 'jumpserver.conf')) + +DB_HOST = config.get('db', 'host') +DB_PORT = config.getint('db', 'port') +DB_USER = config.get('db', 'user') +DB_PASSWORD = config.get('db', 'password') +DB_DATABASE = config.get('db', 'database') -DB_HOST = CF.get('db', 'host') -DB_PORT = CF.getint('db', 'port') -DB_USER = CF.get('db', 'user') -DB_PASSWORD = CF.get('db', 'password') -DB_DB = CF.get('db', 'db') +# mail config +EMAIL_HOST = config.get('mail', 'email_host') +EMAIL_PORT = config.get('mail', 'email_port') +EMAIL_HOST_USER = config.get('mail', 'email_host_user') +EMAIL_HOST_PASSWORD = config.get('mail', 'email_host_password') +EMAIL_USE_TLS = config.getboolean('mail', 'email_use_tls') # Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/ +# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = 'tg-49xz3a#%5@^%83my*2up51)c3pove2_+21_(j*795gm38u*' +SECRET_KEY = '!%=t81uof5rhmtpi&(zr=q^fah#$enny-c@mswz49l42j0o49-' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True TEMPLATE_DEBUG = True -ALLOWED_HOSTS = ['*'] +ALLOWED_HOSTS = ['0.0.0.0/8'] # Application definition @@ -46,10 +53,12 @@ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', - 'UserManage', - 'Assets', - 'AutoSa', - #'RunCommand', + 'django.contrib.humanize', + 'jumpserver', + 'juser', + 'jasset', + 'jperm', + 'jlog', ) MIDDLEWARE_CLASSES = ( @@ -57,22 +66,23 @@ 'django.middleware.common.CommonMiddleware', #'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ) -ROOT_URLCONF = 'AutoSa.urls' +ROOT_URLCONF = 'jumpserver.urls' -WSGI_APPLICATION = 'AutoSa.wsgi.application' +WSGI_APPLICATION = 'jumpserver.wsgi.application' # Database -# https://docs.djangoproject.com/en/1.6/ref/settings/#databases +# https://docs.djangoproject.com/en/1.7/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', - 'NAME': DB_DB, + 'NAME': DB_DATABASE, 'USER': DB_USER, 'PASSWORD': DB_PASSWORD, 'HOST': DB_HOST, @@ -88,7 +98,7 @@ 'django.core.context_processors.static', 'django.core.context_processors.tz', 'django.contrib.messages.context_processors.messages', - 'AutoSa.context_processors.name_proc', + 'jumpserver.context_processors.name_proc' ) TEMPLATE_DIRS = ( @@ -100,11 +110,10 @@ STATICFILES_DIRS = ( os.path.join(BASE_DIR, "static"), ) - # Internationalization -# https://docs.djangoproject.com/en/1.6/topics/i18n/ +# https://docs.djangoproject.com/en/1.7/topics/i18n/ -LANGUAGE_CODE = 'zh-cn' +LANGUAGE_CODE = 'en-us' TIME_ZONE = 'Asia/Shanghai' @@ -112,12 +121,12 @@ USE_L10N = True -USE_TZ = True +USE_TZ = False # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/1.6/howto/static-files/ +# https://docs.djangoproject.com/en/1.7/howto/static-files/ STATIC_URL = '/static/' -SESSION_COOKIE_AGE = 3600 + diff --git a/jumpserver/templatetags/__init__.py b/jumpserver/templatetags/__init__.py new file mode 100644 index 000000000000..bfd53d39fa18 --- /dev/null +++ b/jumpserver/templatetags/__init__.py @@ -0,0 +1 @@ +__author__ = 'Hudie' diff --git a/jumpserver/templatetags/mytags.py b/jumpserver/templatetags/mytags.py new file mode 100644 index 000000000000..ee2f05c13252 --- /dev/null +++ b/jumpserver/templatetags/mytags.py @@ -0,0 +1,394 @@ +# coding: utf-8 + +import re +import ast +import time + +from django import template +from jperm.models import CmdGroup +from jumpserver.api import * +from jasset.models import AssetAlias + +register = template.Library() + + +@register.filter(name='stamp2str') +def stamp2str(value): + try: + return time.strftime('%Y/%m/%d %H:%M:%S', time.localtime(value)) + except AttributeError: + return '0000/00/00 00:00:00' + + +@register.filter(name='int2str') +def int2str(value): + return str(value) + + +@register.filter(name='get_role') +def get_role(user_id): + user_role = {'SU': u'超级管理员', 'DA': u'部门管理员', 'CU': u'普通用户'} + user = User.objects.filter(id=user_id) + if user: + user = user[0] + return user_role.get(str(user.role), u"普通用户") + else: + return u"普通用户" + + +@register.filter(name='groups_str') +def groups_str(user_id): + groups = [] + user = User.objects.get(id=user_id) + for group in user.group.all(): + groups.append(group.name) + if len(groups) < 3: + return ' '.join(groups) + else: + return "%s ..." % ' '.join(groups[0:2]) + + +@register.filter(name='group_str2') +def groups_str2(group_list): + if len(group_list) < 3: + return ' '.join([group.name for group in group_list]) + else: + return '%s ...' % ' '.join([group.name for group in group_list[0:2]]) + + +@register.filter(name='group_str2_all') +def group_str2_all(group_list): + group_lis = [] + for i in group_list: + if str(i) != 'ALL': + group_lis.append(i) + if len(group_lis) < 3: + return ' '.join([group.name for group in group_lis]) + else: + return '%s ...' % ' '.join([group.name for group in group_lis[0:2]]) + + +@register.filter(name='group_dept_all') +def group_dept_all(group_list): + group_lis = [] + for i in group_list: + if str(i) != 'ALL': + group_lis.append(i) + return ' '.join([group.name for group in group_lis]) + + +@register.filter(name='group_manage_str') +def group_manage_str(username): + user = User.objects.get(username=username) + group = user.user_group.filter(type='M') + if group: + return group[0].name + else: + return '' + + +@register.filter(name='get_item') +def get_item(dictionary, key): + return dictionary.get(key) + + +@register.filter(name='get_login_type') +def get_login_type(login): + login_types = {'L': 'LDAP', 'M': 'MAP'} + return login_types[login] + + +@register.filter(name='bool2str') +def bool2str(value): + if value: + return u'是' + else: + return u'否' + + +# @register.filter(name='user_readonly') +# def user_readonly(user_id): +# user = User.objects.filter(id=user_id) +# if user: +# user = user[0] +# if user.role == 'CU': +# return False +# return True +# + +@register.filter(name='member_count') +def member_count(group_id): + group = UserGroup.objects.get(id=group_id) + return group.user_set.count() + + +@register.filter(name='group_user_count') +def group_user_count(group_id): + group = UserGroup.objects.get(id=group_id) + return group.user_set.count() + + +@register.filter(name='dept_user_num') +def dept_user_num(dept_id): + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept = dept[0] + return dept.user_set.count() + else: + return 0 + + +@register.filter(name='dept_group_num') +def dept_group_num(dept_id): + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept = dept[0] + return dept.usergroup_set.all().count() + else: + return 0 + + +@register.filter(name='perm_count') +def perm_count(group_id): + group = UserGroup.objects.get(id=group_id) + return group.perm_set.count() + + +@register.filter(name='dept_asset_num') +def dept_asset_num(dept_id): + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept = dept[0] + return dept.asset_set.all().count() + return 0 + + +@register.filter(name='ugrp_perm_agrp_count') +def ugrp_perm_agrp_count(user_group_id): + user_group = UserGroup.objects.filter(id=user_group_id) + if user_group: + user_group = user_group[0] + return user_group.perm_set.all().count() + return 0 + + +@register.filter(name='ugrp_sudo_agrp_count') +def ugrp_sudo_agrp_count(user_group_id): + user_group = UserGroup.objects.filter(id=user_group_id) + asset_groups = [] + if user_group: + user_group = user_group[0] + for perm in user_group.sudoperm_set.all(): + asset_groups.extend(perm.asset_group.all()) + return len(set(asset_groups)) + return 0 + + +@register.filter(name='ugrp_perm_asset_count') +def ugrp_perm_asset_count(user_group_id): + user_group = UserGroup.objects.filter(id=user_group_id) + assets = [] + if user_group: + user_group = user_group[0] + asset_groups = [perm.asset_group for perm in user_group.perm_set.all()] + for asset_group in asset_groups: + assets.extend(asset_group.asset_set.all()) + return len(set(assets)) + + +@register.filter(name='ugrp_sudo_asset_count') +def ugrp_sudo_asset_count(user_group_id): + user_group = UserGroup.objects.filter(id=user_group_id) + asset_groups = [] + assets = [] + if user_group: + user_group = user_group[0] + for perm in user_group.sudoperm_set.all(): + asset_groups.extend(perm.asset_group.all()) + + for asset_group in asset_groups: + assets.extend(asset_group.asset_set.all()) + return len(set(assets)) + + +@register.filter(name='get_user_alias') +def get_user_alias(post, user_id): + user = User.objects.get(id=user_id) + host = Asset.objects.get(id=post.id) + alias = AssetAlias.objects.filter(user=user, host=host) + if alias: + return alias[0].alias + else: + return '' + + +@register.filter(name='group_type_to_str') +def group_type_to_str(type_name): + group_types = { + 'P': '用户', + 'M': '部门', + 'A': '用户组', + } + return group_types.get(type_name) + + +@register.filter(name='ast_to_list') +def ast_to_list(lis): + ast_lis = ast.literal_eval(lis) + if len(ast_lis) <= 2: + return ','.join([i for i in ast_lis]) + else: + restr = ','.join([i for i in ast_lis[0:2]]) + '...' + return restr + + +@register.filter(name='get_group_count') +def get_group_count(post, dept): + count = post.asset_set.filter(dept=dept).count() + return count + + +@register.filter(name='get_idc_count') +def get_idc_count(post, dept): + count = post.asset_set.filter(dept=dept).count() + return count + + +@register.filter(name='ast_to_list_1') +def ast_to_list_1(lis): + return ast.literal_eval(lis) + + +@register.filter(name='string_length') +def string_length(string, length): + return '%s ...' % string[0:length] + + +@register.filter(name='to_name') +def to_name(user_id): + try: + user = User.objects.filter(id=int(user_id)) + if user: + user = user[0] + return user.name + except: + return '非法用户' + + +@register.filter(name='to_dept_name') +def to_dept_name(user_id): + try: + user = User.objects.filter(id=int(user_id)) + if user: + user = user[0] + return user.dept.name + except: + return '非法部门' + + +@register.filter(name='to_role_name') +def to_role_name(role_id): + role_dict = {'0': '普通用户', '1': '部门管理员', '2': '超级管理员'} + return role_dict.get(str(role_id), '未知') + + +@register.filter(name='to_avatar') +def to_avatar(role_id='0'): + role_dict = {'0': 'user', '1': 'admin', '2': 'root'} + return role_dict.get(str(role_id), 'user') + + +@register.filter(name='get_user_asset_group') +def get_user_asset_group(user): + return user_perm_group_api(user) + + +@register.filter(name='group_asset_list') +def group_asset_list(group): + return group.asset_set.all() + + +@register.filter(name='group_asset_list_count') +def group_asset_list_count(group): + return group.asset_set.all().count() + + +@register.filter(name='time_delta') +def time_delta(time_before): + delta = datetime.datetime.now() - time_before + days = delta.days + if days: + return "%s 天前" % days + else: + hours = delta.seconds/3600 + if hours: + return "%s 小时前" % hours + else: + mins = delta.seconds/60 + if mins: + return '%s 分钟前' % mins + else: + return '%s 秒前' % delta.seconds + + +@register.filter(name='sudo_cmd_list') +def sudo_cmd_list(cmd_group_id): + cmd_group = CmdGroup.objects.filter(id=cmd_group_id) + if cmd_group: + cmd_group = cmd_group[0] + return cmd_group.cmd.split(',') + + +@register.filter(name='sudo_cmd_count') +def sudo_cmd_count(user_group_id): + user_group = UserGroup.objects.filter(id=user_group_id) + cmds = [] + if user_group: + user_group = user_group[0] + cmd_groups = [] + + for perm in user_group.sudoperm_set.all(): + cmd_groups.extend(perm.cmd_group.all()) + + for cmd_group in cmd_groups: + cmds.extend(cmd_group.cmd.split(',')) + return len(set(cmds)) + + else: + return 0 + + +@register.filter(name='sudo_cmd_count') +def sudo_cmd_count(user_group_id): + user_group = UserGroup.objects.filter(id=user_group_id) + cmds = [] + if user_group: + user_group = user_group[0] + cmd_groups = [] + for perm in user_group.sudoperm_set.all(): + cmd_groups.extend(perm.cmd_group.all()) + + for cmd_group in cmd_groups: + cmds.extend(cmd_group.cmd.split(',')) + return len(set(cmds)) + else: + return 0 + + +@register.filter(name='sudo_cmd_ids') +def sudo_cmd_ids(user_group_id): + user_group = UserGroup.objects.filter(id=user_group_id) + if user_group: + user_group = user_group[0] + cmd_groups = [] + for perm in user_group.sudoperm_set.all(): + cmd_groups.extend(perm.cmd_group.all()) + cmd_ids = [str(cmd_group.id) for cmd_group in cmd_groups] + return ','.join(cmd_ids) + else: + return '0' + + +@register.filter(name='cmd_group_split') +def cmd_group_split(cmd_group): + return cmd_group.cmd.split(',') diff --git a/jumpserver/urls.py b/jumpserver/urls.py new file mode 100644 index 000000000000..f6019aa5d95c --- /dev/null +++ b/jumpserver/urls.py @@ -0,0 +1,21 @@ +from django.conf.urls import patterns, include, url + + +urlpatterns = patterns('', + # Examples: + (r'^$', 'jumpserver.views.index'), + (r'^api/user/$', 'jumpserver.api.api_user'), + (r'^skin_config/$', 'jumpserver.views.skin_config'), + (r'^install/$', 'jumpserver.views.install'), + (r'^base/$', 'jumpserver.views.base'), + (r'^login/$', 'jumpserver.views.login'), + (r'^logout/$', 'jumpserver.views.logout'), + (r'^file/upload/$', 'jumpserver.views.upload'), + (r'^file/download/$', 'jumpserver.views.download'), + (r'^error/$', 'jumpserver.views.httperror'), + (r'^juser/', include('juser.urls')), + (r'^jasset/', include('jasset.urls')), + (r'^jlog/', include('jlog.urls')), + (r'^jperm/', include('jperm.urls')), + +) diff --git a/jumpserver/views.py b/jumpserver/views.py new file mode 100644 index 000000000000..005baa162b51 --- /dev/null +++ b/jumpserver/views.py @@ -0,0 +1,313 @@ +# coding: utf-8 + +from __future__ import division +from django.db.models import Count +from django.shortcuts import render_to_response +from django.template import RequestContext +from django.http import HttpResponseNotFound +from jperm.models import Apply +import paramiko +from jumpserver.api import * + + +def getDaysByNum(num): + today = datetime.date.today() + oneday = datetime.timedelta(days=1) + li_date, li_str = [], [] + for i in range(0, num): + today = today-oneday + li_date.append(today) + li_str.append(str(today)[5:10]) + li_date.reverse() + li_str.reverse() + t = (li_date, li_str) + return t + + +def get_data(data, items, option): + dic = {} + li_date, li_str = getDaysByNum(7) + for item in items: + li = [] + name = item[option] + if option == 'user': + option_data = data.filter(user=name) + elif option == 'host': + option_data = data.filter(host=name) + for t in li_date: + year, month, day = t.year, t.month, t.day + times = option_data.filter(start_time__year=year, start_time__month=month, start_time__day=day).count() + li.append(times) + dic[name] = li + return dic + + +@require_login +def index_cu(request): + user_id = request.session.get('user_id') + user = User.objects.filter(id=user_id) + if user: + user = user[0] + login_types = {'L': 'LDAP', 'M': 'MAP'} + user_id = request.session.get('user_id') + username = User.objects.get(id=user_id).username + posts = user_perm_asset_api(username) + host_count = len(posts) + new_posts = [] + post_five = [] + for post in posts: + if len(post_five) < 5: + post_five.append(post) + else: + new_posts.append(post_five) + post_five = [] + new_posts.append(post_five) + + return render_to_response('index_cu.html', locals(), context_instance=RequestContext(request)) + + +@require_login +def index(request): + li_date, li_str = getDaysByNum(7) + today = datetime.datetime.now().day + from_week = datetime.datetime.now() - datetime.timedelta(days=7) + + if is_common_user(request): + return index_cu(request) + + elif is_super_user(request): + users = User.objects.all() + hosts = Asset.objects.all() + online = Log.objects.filter(is_finished=0) + online_host = online.values('host').distinct() + online_user = online.values('user').distinct() + active_users = User.objects.filter(is_active=1) + active_hosts = Asset.objects.filter(is_active=1) + week_data = Log.objects.filter(start_time__range=[from_week, datetime.datetime.now()]) + + elif is_group_admin(request): + user = get_session_user_info(request)[2] + dept_name, dept = get_session_user_info(request)[4:] + users = User.objects.filter(dept=dept) + hosts = Asset.objects.filter(dept=dept) + online = Log.objects.filter(dept_name=dept_name, is_finished=0) + online_host = online.values('host').distinct() + online_user = online.values('user').distinct() + active_users = users.filter(is_active=1) + active_hosts = hosts.filter(is_active=1) + week_data = Log.objects.filter(dept_name=dept_name, start_time__range=[from_week, datetime.datetime.now()]) + + # percent of dashboard + if users.count() == 0: + percent_user, percent_online_user = '0%', '0%' + else: + percent_user = format(active_users.count() / users.count(), '.0%') + percent_online_user = format(online_user.count() / users.count(), '.0%') + if hosts.count() == 0: + percent_host, percent_online_host = '0%', '0%' + else: + percent_host = format(active_hosts.count() / hosts.count(), '.0%') + percent_online_host = format(online_host.count() / hosts.count(), '.0%') + + user_top_ten = week_data.values('user').annotate(times=Count('user')).order_by('-times')[:10] + host_top_ten = week_data.values('host').annotate(times=Count('host')).order_by('-times')[:10] + user_dic, host_dic = get_data(week_data, user_top_ten, 'user'), get_data(week_data, host_top_ten, 'host') + + # a week data + week_users = week_data.values('user').distinct().count() + week_hosts = week_data.count() + + user_top_five = week_data.values('user').annotate(times=Count('user')).order_by('-times')[:5] + color = ['label-success', 'label-info', 'label-primary', 'label-default', 'label-warnning'] + + # perm apply latest 10 + perm_apply_10 = Apply.objects.order_by('-date_add')[:10] + + # latest 10 login + login_10 = Log.objects.order_by('-start_time')[:10] + login_more_10 = Log.objects.order_by('-start_time')[10:21] + + # a week top 10 + for user_info in user_top_ten: + username = user_info.get('user') + last = Log.objects.filter(user=username).latest('start_time') + user_info['last'] = last + + top = {'user': '活跃用户数', 'host': '活跃主机数', 'times': '登录次数'} + top_dic = {} + for key, value in top.items(): + li = [] + for t in li_date: + year, month, day = t.year, t.month, t.day + if key != 'times': + times = week_data.filter(start_time__year=year, start_time__month=month, start_time__day=day).values(key).distinct().count() + else: + times = week_data.filter(start_time__year=year, start_time__month=month, start_time__day=day).count() + li.append(times) + top_dic[value] = li + return render_to_response('index.html', locals(), context_instance=RequestContext(request)) + + +def skin_config(request): + return render_to_response('skin_config.html') + + +def pages(posts, r): + """分页公用函数""" + contact_list = posts + p = paginator = Paginator(contact_list, 10) + try: + current_page = int(r.GET.get('page', '1')) + except ValueError: + current_page = 1 + + page_range = page_list_return(len(p.page_range), current_page) + + try: + contacts = paginator.page(current_page) + except (EmptyPage, InvalidPage): + contacts = paginator.page(paginator.num_pages) + + if current_page >= 5: + show_first = 1 + else: + show_first = 0 + if current_page <= (len(p.page_range) - 3): + show_end = 1 + else: + show_end = 0 + + return contact_list, p, contacts, page_range, current_page, show_first, show_end + + +def login(request): + """登录界面""" + if request.session.get('username'): + return HttpResponseRedirect('/') + if request.method == 'GET': + return render_to_response('login.html') + else: + username = request.POST.get('username') + password = request.POST.get('password') + user_filter = User.objects.filter(username=username) + if user_filter: + user = user_filter[0] + if md5_crypt(password) == user.password: + request.session['user_id'] = user.id + user_filter.update(last_login=datetime.datetime.now()) + if user.role == 'SU': + request.session['role_id'] = 2 + elif user.role == 'DA': + request.session['role_id'] = 1 + else: + request.session['role_id'] = 0 + return HttpResponseRedirect('/') + else: + error = '密码错误,请重新输入。' + else: + error = '用户不存在。' + return render_to_response('login.html', {'error': error}) + + +def logout(request): + request.session.delete() + return HttpResponseRedirect('/login/') + + +def filter_ajax_api(request): + attr = request.GET.get('attr', 'user') + value = request.GET.get('value', '') + if attr == 'user': + contact_list = User.objects.filter(name__icontains=value) + elif attr == "user_group": + contact_list = UserGroup.objects.filter(name__icontains=value) + elif attr == "asset": + contact_list = Asset.objects.filter(ip__icontains=value) + elif attr == "asset": + contact_list = BisGroup.objects.filter(name__icontains=value) + + return render_to_response('filter_ajax_api.html', locals()) + + +def install(request): + from juser.models import DEPT, User + if User.objects.filter(id=5000): + return httperror(request, 'Jumpserver已初始化,不能重复安装!') + + dept = DEPT(id=1, name="超管部", comment="超级管理部门") + dept.save() + dept2 = DEPT(id=2, name="默认", comment="默认部门") + dept2.save() + IDC(id=1, name="默认", comment="默认IDC").save() + BisGroup(id=1, name="ALL", dept=dept, comment="所有主机组").save() + + User(id=5000, username="admin", password=md5_crypt('admin'), + name='admin', email='admin@jumpserver.org', role='SU', is_active=True, dept=dept).save() + return success(request, u'Jumpserver初始化成功') + + +def download(request): + return render_to_response('download.html', locals(), context_instance=RequestContext(request)) + + +def transfer(sftp, filenames): + # pool = Pool(processes=5) + for filename, file_path in filenames.items(): + print filename, file_path + sftp.put(file_path, '/tmp/%s' % filename) + # pool.apply_async(transfer, (sftp, file_path, '/tmp/%s' % filename)) + sftp.close() + # pool.close() + # pool.join() + + +def upload(request): + user, dept = get_session_user_dept(request) + if request.method == 'POST': + hosts = request.POST.get('hosts') + upload_files = request.FILES.getlist('file[]', None) + upload_dir = "/tmp/%s" % user.username + is_dir(upload_dir) + date_now = datetime.datetime.now().strftime("%Y%m%d%H%M%S") + hosts_list = hosts.split(',') + user_hosts = get_user_host(user.username).keys() + unperm_hosts = [] + filenames = {} + for ip in hosts_list: + if ip not in user_hosts: + unperm_hosts.append(ip) + + if not hosts: + return HttpResponseNotFound(u'地址不能为空') + + if unperm_hosts: + print hosts_list + return HttpResponseNotFound(u'%s 没有权限.' % ', '.join(unperm_hosts)) + + for upload_file in upload_files: + file_path = '%s/%s.%s' % (upload_dir, upload_file.name, date_now) + filenames[upload_file.name] = file_path + f = open(file_path, 'w') + for chunk in upload_file.chunks(): + f.write(chunk) + f.close() + + sftps = [] + for host in hosts_list: + username, password, host, port = get_connect_item(user.username, host) + try: + t = paramiko.Transport((host, port)) + t.connect(username=username, password=password) + sftp = paramiko.SFTPClient.from_transport(t) + sftps.append(sftp) + except paramiko.AuthenticationException: + return HttpResponseNotFound(u'%s 连接失败.' % host) + + # pool = Pool(processes=5) + for sftp in sftps: + transfer(sftp, filenames) + # pool.close() + # pool.join() + return HttpResponse('传送成功') + + return render_to_response('upload.html', locals(), context_instance=RequestContext(request)) diff --git a/webroot/AutoSa/AutoSa/wsgi.py b/jumpserver/wsgi.py similarity index 50% rename from webroot/AutoSa/AutoSa/wsgi.py rename to jumpserver/wsgi.py index 178504cbf050..cf26c6b87e94 100644 --- a/webroot/AutoSa/AutoSa/wsgi.py +++ b/jumpserver/wsgi.py @@ -1,16 +1,14 @@ """ -WSGI config for AutoSa project. +WSGI config for jumpserver project. It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/1.6/howto/deployment/wsgi/ +https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/ """ import os -import sys -sys.path.append('/opt/jumpserver/webroot/AutoSa') -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "AutoSa.settings") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "jumpserver.settings") from django.core.wsgi import get_wsgi_application application = get_wsgi_application() diff --git a/keys/test.pub b/juser/__init__.py similarity index 100% rename from keys/test.pub rename to juser/__init__.py diff --git a/juser/admin.py b/juser/admin.py new file mode 100644 index 000000000000..8c38f3f3dad5 --- /dev/null +++ b/juser/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/juser/models.py b/juser/models.py new file mode 100644 index 000000000000..d7efd7a28d15 --- /dev/null +++ b/juser/models.py @@ -0,0 +1,41 @@ +from django.db import models + + +class DEPT(models.Model): + name = models.CharField(max_length=80, unique=True) + comment = models.CharField(max_length=160, blank=True, null=True) + + def __unicode__(self): + return self.name + + +class UserGroup(models.Model): + name = models.CharField(max_length=80, unique=True) + dept = models.ForeignKey(DEPT) + comment = models.CharField(max_length=160, blank=True, null=True) + + def __unicode__(self): + return self.name + + +class User(models.Model): + USER_ROLE_CHOICES = ( + ('SU', 'SuperUser'), + ('DA', 'DeptAdmin'), + ('CU', 'CommonUser'), + ) + username = models.CharField(max_length=80, unique=True) + password = models.CharField(max_length=100) + name = models.CharField(max_length=80) + email = models.EmailField(max_length=75) + role = models.CharField(max_length=2, choices=USER_ROLE_CHOICES, default='CU') + dept = models.ForeignKey(DEPT) + group = models.ManyToManyField(UserGroup) + ldap_pwd = models.CharField(max_length=100) + ssh_key_pwd = models.CharField(max_length=100) + is_active = models.BooleanField(default=True) + last_login = models.DateTimeField(null=True) + date_joined = models.DateTimeField(null=True) + + def __unicode__(self): + return self.username diff --git a/juser/tests.py b/juser/tests.py new file mode 100644 index 000000000000..7ce503c2dd97 --- /dev/null +++ b/juser/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/juser/urls.py b/juser/urls.py new file mode 100644 index 000000000000..cbaba7bb0203 --- /dev/null +++ b/juser/urls.py @@ -0,0 +1,33 @@ +from django.conf.urls import patterns, include, url +from jumpserver.api import view_splitter +from juser.views import * + +urlpatterns = patterns('juser.views', + # Examples: + # url(r'^$', 'jumpserver.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + + (r'^dept_list/$', view_splitter, {'su': dept_list, 'adm': dept_list_adm}), + (r'^dept_add/$', 'dept_add'), + (r'^dept_del/$', 'dept_del'), + (r'^dept_detail/$', 'dept_detail'), + (r'^dept_del_ajax/$', 'dept_del_ajax'), + (r'^dept_edit/$', 'dept_edit'), + (r'^dept_user_ajax/$', 'dept_user_ajax'), + (r'^group_add/$', view_splitter, {'su': group_add, 'adm': group_add_adm}), + (r'^group_list/$', view_splitter, {'su': group_list, 'adm': group_list_adm}), + (r'^group_detail/$', 'group_detail'), + (r'^group_del/$', view_splitter, {'su': group_del, 'adm': group_del_adm}), + (r'^group_del_ajax/$', 'group_del_ajax'), + (r'^group_edit/$', view_splitter, {'su': group_edit, 'adm': group_edit_adm}), + (r'^user_add/$', view_splitter, {'su': user_add, 'adm': user_add_adm}), + (r'^user_list/$', view_splitter, {'su': user_list, 'adm': user_list_adm}), + (r'^user_detail/$', 'user_detail'), + (r'^user_del/$', 'user_del'), + (r'^user_del_ajax/$', 'user_del_ajax'), + (r'^user_edit/$', view_splitter, {'su': user_edit, 'adm': user_edit_adm}), + (r'^profile/$', 'profile'), + (r'^chg_info/$', 'chg_info'), + (r'^chg_role/$', 'chg_role'), + (r'^down_key/$', 'down_key'), +) diff --git a/juser/views.py b/juser/views.py new file mode 100644 index 000000000000..0fd6ee4c019d --- /dev/null +++ b/juser/views.py @@ -0,0 +1,1050 @@ +# coding: utf-8 +# Author: Guanghongwei +# Email: ibuler@qq.com + +import random +from Crypto.PublicKey import RSA +import crypt + +from django.shortcuts import render_to_response +from django.db.models import Q +from django.template import RequestContext + +from jumpserver.api import * + + +def gen_rand_pwd(num): + """生成随机密码""" + seed = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + salt_list = [] + for i in range(num): + salt_list.append(random.choice(seed)) + salt = ''.join(salt_list) + return salt + + +class AddError(Exception): + pass + + +def gen_sha512(salt, password): + return crypt.crypt(password, '$6$%s$' % salt) + + +def group_add_user(group, user_id=None, username=None): + try: + if user_id: + user = User.objects.get(id=user_id) + else: + user = User.objects.get(username=username) + except ObjectDoesNotExist: + raise AddError('用户获取失败') + else: + group.user_set.add(user) + + +def db_add_group(**kwargs): + name = kwargs.get('name') + group = UserGroup.objects.filter(name=name) + users = kwargs.pop('users') + if group: + raise AddError(u'用户组 %s 已经存在' % name) + group = UserGroup(**kwargs) + group.save() + for user_id in users: + group_add_user(group, user_id) + + +def db_add_user(**kwargs): + groups_post = kwargs.pop('groups') + user = User(**kwargs) + user.save() + if groups_post: + group_select = [] + for group_id in groups_post: + group = UserGroup.objects.filter(id=group_id) + group_select.extend(group) + user.group = group_select + return user + + +def db_update_user(**kwargs): + print kwargs + groups_post = kwargs.pop('groups') + user_id = kwargs.pop('user_id') + user = User.objects.filter(id=user_id) + if user: + user.update(**kwargs) + user = User.objects.get(id=user_id) + user.save() + + if groups_post: + group_select = [] + for group_id in groups_post: + group = UserGroup.objects.filter(id=group_id) + group_select.extend(group) + user.group = group_select + + +def db_del_user(username): + try: + user = User.objects.get(username=username) + user.delete() + except ObjectDoesNotExist: + pass + + +def gen_ssh_key(username, password=None, length=2048): + private_key_dir = os.path.join(BASE_DIR, 'keys/jumpserver/') + private_key_file = os.path.join(private_key_dir, username+".pem") + public_key_dir = '/home/%s/.ssh/' % username + public_key_file = os.path.join(public_key_dir, 'authorized_keys') + is_dir(private_key_dir) + is_dir(public_key_dir, username, mode=0700) + + key = RSA.generate(length) + with open(private_key_file, 'w') as pri_f: + pri_f.write(key.exportKey('PEM', password)) + os.chmod(private_key_file, 0600) + + pub_key = key.publickey() + with open(public_key_file, 'w') as pub_f: + pub_f.write(pub_key.exportKey('OpenSSH')) + os.chmod(public_key_file, 0600) + bash('chown %s:%s %s' % (username, username, public_key_file)) + + +def server_add_user(username, password, ssh_key_pwd): + bash("useradd '%s'; echo '%s' | passwd --stdin '%s'" % (username, password, username)) + gen_ssh_key(username, ssh_key_pwd) + + +def server_del_user(username): + bash('userdel -r %s' % username) + + +def ldap_add_user(username, ldap_pwd): + user_dn = "uid=%s,ou=People,%s" % (username, LDAP_BASE_DN) + password_sha512 = gen_sha512(gen_rand_pwd(6), ldap_pwd) + user = User.objects.filter(username=username) + if user: + user = user[0] + else: + raise AddError(u'用户 %s 不存在' % username) + + user_attr = {'uid': [str(username)], + 'cn': [str(username)], + 'objectClass': ['account', 'posixAccount', 'top', 'shadowAccount'], + 'userPassword': ['{crypt}%s' % password_sha512], + 'shadowLastChange': ['16328'], + 'shadowMin': ['0'], + 'shadowMax': ['99999'], + 'shadowWarning': ['7'], + 'loginShell': ['/bin/bash'], + 'uidNumber': [str(user.id)], + 'gidNumber': [str(user.id)], + 'homeDirectory': [str('/home/%s' % username)]} + + group_dn = "cn=%s,ou=Group,%s" % (username, LDAP_BASE_DN) + group_attr = {'objectClass': ['posixGroup', 'top'], + 'cn': [str(username)], + 'userPassword': ['{crypt}x'], + 'gidNumber': [str(user.id)]} + + ldap_conn.add(user_dn, user_attr) + ldap_conn.add(group_dn, group_attr) + + +def ldap_del_user(username): + user_dn = "uid=%s,ou=People,%s" % (username, LDAP_BASE_DN) + group_dn = "cn=%s,ou=Group,%s" % (username, LDAP_BASE_DN) + sudo_dn = 'cn=%s,ou=Sudoers,%s' % (username, LDAP_BASE_DN) + + ldap_conn.delete(user_dn) + ldap_conn.delete(group_dn) + ldap_conn.delete(sudo_dn) + + +@require_super_user +def dept_add(request): + header_title, path1, path2 = '添加部门', '用户管理', '添加部门' + if request.method == 'POST': + name = request.POST.get('name', '') + comment = request.POST.get('comment', '') + + try: + if not name: + raise AddError('部门名称不能为空') + if DEPT.objects.filter(name=name): + raise AddError(u'部门名称 %s 已存在' % name) + except AddError, e: + error = e + else: + DEPT(name=name, comment=comment).save() + msg = u'添加部门 %s 成功' % name + + return render_to_response('juser/dept_add.html', locals(), context_instance=RequestContext(request)) + + +@require_super_user +def dept_list(request): + header_title, path1, path2 = '查看部门', '用户管理', '查看部门' + keyword = request.GET.get('search') + if keyword: + contact_list = DEPT.objects.filter(Q(name__icontains=keyword) | Q(comment__icontains=keyword)).order_by('name') + else: + contact_list = DEPT.objects.all().order_by('id') + + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(contact_list, request) + + return render_to_response('juser/dept_list.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def dept_list_adm(request): + header_title, path1, path2 = '查看部门', '用户管理', '查看部门' + user, dept = get_session_user_dept(request) + contact_list = [dept] + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(contact_list, request) + + return render_to_response('juser/dept_list.html', locals(), context_instance=RequestContext(request)) + + +def chg_role(request): + role = {'SU': 2, 'DA': 1, 'CU': 0} + user, dept = get_session_user_dept(request) + if request.session['role_id'] > 0: + request.session['role_id'] = 0 + elif request.session['role_id'] == 0: + request.session['role_id'] = role.get(user.role, 0) + return HttpResponseRedirect('/') + + +@require_super_user +def dept_detail(request): + dept_id = request.GET.get('id', None) + if not dept_id: + return HttpResponseRedirect('/juser/dept_list/') + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept = dept[0] + users = dept.user_set.all() + return render_to_response('juser/dept_detail.html', locals(), context_instance=RequestContext(request)) + + +@require_super_user +def dept_del(request): + dept_id = request.GET.get('id', None) + if not dept_id or dept_id in ['1', '2']: + return HttpResponseRedirect('/juser/dept_list/') + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept = dept[0] + dept.delete() + return HttpResponseRedirect('/juser/dept_list/') + + +def dept_member(dept_id): + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept = dept[0] + return dept.user_set.all() + + +def dept_member_update(dept, users_id_list): + old_users = dept.user_set.all() + new_users = [] + for user_id in users_id_list: + new_users.extend(User.objects.filter(id=user_id)) + + remove_user = [user for user in old_users if user not in new_users] + add_user = [user for user in new_users if user not in old_users] + + for user in add_user: + user.dept = dept + user.save() + + dept_default = DEPT.objects.get(id=2) + for user in remove_user: + user.dept = dept_default + user.save() + + +@require_super_user +def dept_del_ajax(request): + dept_ids = request.POST.get('dept_ids') + for dept_id in dept_ids.split(','): + if int(dept_id) > 2: + DEPT.objects.filter(id=dept_id).delete() + return HttpResponse("删除成功") + + +@require_super_user +def dept_edit(request): + header_title, path1, path2 = '部门编辑', '用户管理', '部门编辑' + if request.method == 'GET': + dept_id = request.GET.get('id', '') + if dept_id: + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept = dept[0] + users = dept_member(dept_id) + users_all = User.objects.all() + users_other = [user for user in users_all if user not in users] + else: + error = 'id 错误' + else: + error = u'部门不存在' + else: + dept_id = request.POST.get('id', '') + name = request.POST.get('name', '') + users = request.POST.getlist('users_selected', []) + comment = request.POST.get('comment', '') + + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept.update(name=name, comment=comment) + dept_member_update(dept[0], users) + else: + error = '部门不存在' + return HttpResponseRedirect('/juser/dept_list/') + return render_to_response('juser/dept_edit.html', locals(), context_instance=RequestContext(request)) + + +def dept_user_ajax(request): + dept_id = request.GET.get('id', '4') + if dept_id not in ['1', '2']: + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept = dept[0] + users = dept.user_set.all() + else: + users = User.objects.all() + + return render_to_response('juser/dept_user_ajax.html', locals()) + + + +@require_super_user +def group_add(request): + error = '' + msg = '' + header_title, path1, path2 = '添加小组', '用户管理', '添加小组' + user_all = User.objects.all() + dept_all = DEPT.objects.all() + + if request.method == 'POST': + group_name = request.POST.get('group_name', '') + dept_id = request.POST.get('dept_id', '') + users_selected = request.POST.getlist('users_selected', '') + comment = request.POST.get('comment', '') + + try: + if '' in [group_name, dept_id]: + error = u'组名 或 部门 不能为空' + raise AddError(error) + + if UserGroup.objects.filter(name=group_name): + error = u'组名已存在' + raise AddError(error) + + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept = dept[0] + else: + error = u'部门不存在' + raise AddError(error) + + db_add_group(name=group_name, users=users_selected, dept=dept, comment=comment) + except AddError: + pass + except TypeError: + error = u'保存小组失败' + else: + msg = u'添加组 %s 成功' % group_name + + return render_to_response('juser/group_add.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def group_add_adm(request): + error = '' + msg = '' + header_title, path1, path2 = '添加小组', '用户管理', '添加小组' + user, dept = get_session_user_dept(request) + user_all = dept.user_set.all() + + if request.method == 'POST': + group_name = request.POST.get('group_name', '') + users_selected = request.POST.getlist('users_selected', '') + comment = request.POST.get('comment', '') + + try: + if not validate(request, user=users_selected): + raise AddError('没有某用户权限') + if '' in [group_name]: + error = u'组名不能为空' + raise AddError(error) + + db_add_group(name=group_name, users=users_selected, dept=dept, comment=comment) + except AddError: + pass + except TypeError: + error = u'保存小组失败' + else: + msg = u'添加组 %s 成功' % group_name + + return render_to_response('juser/group_add.html', locals(), context_instance=RequestContext(request)) + + +@require_super_user +def group_list(request): + header_title, path1, path2 = '查看小组', '用户管理', '查看小组' + keyword = request.GET.get('search', '') + did = request.GET.get('did', '') + contact_list = UserGroup.objects.all().order_by('name') + + if did: + dept = DEPT.objects.filter(id=did) + if dept: + dept = dept[0] + contact_list = dept.usergroup_set.all() + + if keyword: + contact_list = contact_list.filter(Q(name__icontains=keyword) | Q(comment__icontains=keyword)) + + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(contact_list, request) + return render_to_response('juser/group_list.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def group_list_adm(request): + header_title, path1, path2 = '查看部门小组', '用户管理', '查看小组' + keyword = request.GET.get('search', '') + did = request.GET.get('did', '') + user, dept = get_session_user_dept(request) + contact_list = dept.usergroup_set.all().order_by('name') + + if keyword: + contact_list = contact_list.filter(Q(name__icontains=keyword) | Q(comment__icontains=keyword)) + + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(contact_list, request) + return render_to_response('juser/group_list.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def group_detail(request): + group_id = request.GET.get('id', None) + if not group_id: + return HttpResponseRedirect('/') + group = UserGroup.objects.get(id=group_id) + users = group.user_set.all() + return render_to_response('juser/group_detail.html', locals(), context_instance=RequestContext(request)) + + +@require_super_user +def group_del(request): + group_id = request.GET.get('id', '') + if not group_id: + return HttpResponseRedirect('/') + UserGroup.objects.filter(id=group_id).delete() + return HttpResponseRedirect('/juser/group_list/') + + +@require_admin +def group_del_adm(request): + group_id = request.GET.get('id', '') + if not validate(request, user_group=[group_id]): + return HttpResponseRedirect('/juser/group_list/') + if not group_id: + return HttpResponseRedirect('/') + UserGroup.objects.filter(id=group_id).delete() + return HttpResponseRedirect('/juser/group_list/') + + +@require_admin +def group_del_ajax(request): + group_ids = request.POST.get('group_ids') + group_ids = group_ids.split(',') + if request.session.get('role_id') == 1: + if not validate(request, user_group=group_ids): + return "error" + for group_id in group_ids: + UserGroup.objects.filter(id=group_id).delete() + return HttpResponse('删除成功') + + +def group_update_member(group_id, users_id_list): + group = UserGroup.objects.filter(id=group_id) + if group: + group = group[0] + group.user_set.clear() + for user_id in users_id_list: + user = User.objects.get(id=user_id) + group.user_set.add(user) + + +@require_super_user +def group_edit(request): + error = '' + msg = '' + header_title, path1, path2 = '修改小组信息', '用户管理', '编辑小组' + if request.method == 'GET': + group_id = request.GET.get('id', '') + group = UserGroup.objects.filter(id=group_id) + if group: + group = group[0] + dept_all = DEPT.objects.all() + users_all = User.objects.all() + users_selected = group.user_set.all() + users = [user for user in users_all if user not in users_selected] + + return render_to_response('juser/group_edit.html', locals(), context_instance=RequestContext(request)) + else: + group_id = request.POST.get('group_id', '') + group_name = request.POST.get('group_name', '') + dept_id = request.POST.get('dept_id', '') + comment = request.POST.get('comment', '') + users_selected = request.POST.getlist('users_selected') + + users = [] + try: + if '' in [group_id, group_name]: + raise AddError('组名不能为空') + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept = dept[0] + else: + raise AddError('部门不存在') + for user_id in users_selected: + users.extend(User.objects.filter(id=user_id)) + + user_group = UserGroup.objects.filter(id=group_id) + if user_group: + user_group.update(name=group_name, comment=comment, dept=dept) + user_group = user_group[0] + user_group.user_set.clear() + user_group.user_set = users + + except AddError, e: + error = e + + return HttpResponseRedirect('/juser/group_list/') + + +@require_admin +def group_edit_adm(request): + error = '' + msg = '' + header_title, path1, path2 = '修改小组信息', '用户管理', '编辑小组' + user, dept = get_session_user_dept(request) + if request.method == 'GET': + group_id = request.GET.get('id', '') + if not validate(request, user_group=[group_id]): + return HttpResponseRedirect('/juser/group_list/') + group = UserGroup.objects.filter(id=group_id) + if group: + group = group[0] + users_all = dept.user_set.all() + users_selected = group.user_set.all() + users = [user for user in users_all if user not in users_selected] + + return render_to_response('juser/group_edit.html', locals(), context_instance=RequestContext(request)) + else: + group_id = request.POST.get('group_id', '') + group_name = request.POST.get('group_name', '') + comment = request.POST.get('comment', '') + users_selected = request.POST.getlist('users_selected') + + users = [] + try: + if not validate(request, user=users_selected): + raise AddError(u'右侧非部门用户') + + if not validate(request, user_group=[group_id]): + raise AddError(u'没有权限修改本组') + + for user_id in users_selected: + users.extend(User.objects.filter(id=user_id)) + + user_group = UserGroup.objects.filter(id=group_id) + if user_group: + user_group.update(name=group_name, comment=comment, dept=dept) + user_group = user_group[0] + user_group.user_set.clear() + user_group.user_set = users + + except AddError, e: + error = e + + return HttpResponseRedirect('/juser/group_list/') + + +@require_super_user +def user_add(request): + error = '' + msg = '' + header_title, path1, path2 = '添加用户', '用户管理', '添加用户' + user_role = {'SU': u'超级管理员', 'DA': u'部门管理员', 'CU': u'普通用户'} + dept_all = DEPT.objects.all() + group_all = UserGroup.objects.all() + + if request.method == 'POST': + username = request.POST.get('username', '') + password = gen_rand_pwd(16) + name = request.POST.get('name', '') + email = request.POST.get('email', '') + dept_id = request.POST.get('dept_id') + groups = request.POST.getlist('groups', []) + role_post = request.POST.get('role', 'CU') + ssh_key_pwd = gen_rand_pwd(16) + is_active = True if request.POST.get('is_active', '1') == '1' else False + ldap_pwd = gen_rand_pwd(16) + + try: + if '' in [username, password, ssh_key_pwd, name, groups, role_post, is_active]: + error = u'带*内容不能为空' + raise AddError + user = User.objects.filter(username=username) + if user: + error = u'用户 %s 已存在' % username + raise AddError + + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept = dept[0] + else: + error = u'部门不存在' + raise AddError(error) + + except AddError: + pass + else: + try: + user = db_add_user(username=username, + password=md5_crypt(password), + name=name, email=email, dept=dept, + groups=groups, role=role_post, + ssh_key_pwd=md5_crypt(ssh_key_pwd), + ldap_pwd=CRYPTOR.encrypt(ldap_pwd), + is_active=is_active, + date_joined=datetime.datetime.now()) + + server_add_user(username, password, ssh_key_pwd) + if LDAP_ENABLE: + ldap_add_user(username, ldap_pwd) + mail_title = u'恭喜你的跳板机用户添加成功 Jumpserver' + mail_msg = """ + Hi, %s + 您的用户名: %s + 您的部门: %s + 您的角色: %s + 您的web登录密码: %s + 您的ssh登录密码: %s + 密钥下载地址: http://%s:%s/juser/down_key/?id=%s + 说明: 请登陆后再下载密钥! + """ % (name, username, dept.name, user_role.get(role_post, ''), + password, ssh_key_pwd, SEND_IP, SEND_PORT, user.id) + + except Exception, e: + error = u'添加用户 %s 失败 %s ' % (username, e) + try: + db_del_user(username) + server_del_user(username) + if LDAP_ENABLE: + ldap_del_user(username) + except Exception: + pass + else: + send_mail(mail_title, mail_msg, MAIL_FROM, [email], fail_silently=False) + msg = u'添加用户 %s 成功! 用户密码已发送到 %s 邮箱!' % (username, email) + return render_to_response('juser/user_add.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def user_add_adm(request): + error = '' + msg = '' + header_title, path1, path2 = '添加用户', '用户管理', '添加用户' + user, dept = get_session_user_dept(request) + group_all = dept.usergroup_set.all() + + if request.method == 'POST': + username = request.POST.get('username', '') + password = gen_rand_pwd(16) + name = request.POST.get('name', '') + email = request.POST.get('email', '') + groups = request.POST.getlist('groups', []) + ssh_key_pwd = gen_rand_pwd(16) + is_active = True if request.POST.get('is_active', '1') == '1' else False + ldap_pwd = gen_rand_pwd(16) + + try: + if '' in [username, password, ssh_key_pwd, name, groups, is_active]: + error = u'带*内容不能为空' + raise AddError + user = User.objects.filter(username=username) + if user: + error = u'用户 %s 已存在' % username + raise AddError + + except AddError: + pass + else: + try: + user = db_add_user(username=username, + password=md5_crypt(password), + name=name, email=email, dept=dept, + groups=groups, role='CU', + ssh_key_pwd=md5_crypt(ssh_key_pwd), + ldap_pwd=CRYPTOR.encrypt(ldap_pwd), + is_active=is_active, + date_joined=datetime.datetime.now()) + + server_add_user(username, password, ssh_key_pwd) + if LDAP_ENABLE: + ldap_add_user(username, ldap_pwd) + + except Exception, e: + error = u'添加用户 %s 失败 %s ' % (username, e) + try: + db_del_user(username) + server_del_user(username) + if LDAP_ENABLE: + ldap_del_user(username) + except Exception: + pass + else: + mail_title = u'恭喜你的跳板机用户添加成功 Jumpserver' + mail_msg = """ + Hi, %s + 您的用户名: %s + 您的部门: %s + 您的角色: %s + 您的web登录密码: %s + 您的ssh登录密码: %s + 密钥下载地址: http://%s:%s/juser/down_key/?id=%s + 说明: 请登陆后再下载密钥! + """ % (name, username, dept.name, '普通用户', + password, ssh_key_pwd, SEND_IP, SEND_PORT, user.id) + print MAIL_FROM + send_mail(mail_title, mail_msg, MAIL_FROM, [email], fail_silently=False) + msg = u'添加用户 %s 成功! 用户密码已发送到 %s 邮箱!' % (username, email) + + return render_to_response('juser/user_add.html', locals(), context_instance=RequestContext(request)) + + +@require_super_user +def user_list(request): + user_role = {'SU': u'超级管理员', 'GA': u'组管理员', 'CU': u'普通用户'} + header_title, path1, path2 = '查看用户', '用户管理', '用户列表' + keyword = request.GET.get('keyword', '') + gid = request.GET.get('gid', '') + did = request.GET.get('did', '') + contact_list = User.objects.all().order_by('name') + + if gid: + user_group = UserGroup.objects.filter(id=gid) + if user_group: + user_group = user_group[0] + contact_list = user_group.user_set.all() + + if did: + dept = DEPT.objects.filter(id=did) + if dept: + dept = dept[0] + contact_list = dept.user_set.all().order_by('name') + + if keyword: + contact_list = contact_list.filter(Q(username__icontains=keyword) | Q(name__icontains=keyword)).order_by('name') + + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(contact_list, request) + + return render_to_response('juser/user_list.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def user_list_adm(request): + user_role = {'SU': u'超级管理员', 'GA': u'组管理员', 'CU': u'普通用户'} + header_title, path1, path2 = '查看用户', '用户管理', '用户列表' + keyword = request.GET.get('keyword', '') + user, dept = get_session_user_dept(request) + gid = request.GET.get('gid', '') + contact_list = dept.user_set.all().order_by('name') + + if gid: + if not validate(request, user_group=[gid]): + return HttpResponseRedirect('/juser/user_list/') + user_group = UserGroup.objects.filter(id=gid) + if user_group: + user_group = user_group[0] + contact_list = user_group.user_set.all() + + if keyword: + contact_list = contact_list.filter(Q(username__icontains=keyword) | Q(name__icontains=keyword)).order_by('name') + + contact_list, p, contacts, page_range, current_page, show_first, show_end = pages(contact_list, request) + + return render_to_response('juser/user_list.html', locals(), context_instance=RequestContext(request)) + + +@require_login +def user_detail(request): + header_title, path1, path2 = '查看用户', '用户管理', '用户详情' + if request.session.get('role_id') == 0: + user_id = request.session.get('user_id') + else: + user_id = request.GET.get('id', '') + if request.session.get('role_id') == 1: + user, dept = get_session_user_dept(request) + if not validate(request, user=[user_id]): + return HttpResponseRedirect('/') + if not user_id: + return HttpResponseRedirect('/juser/user_list/') + + user = User.objects.filter(id=user_id) + if user: + user = user[0] + asset_group_permed = user_perm_group_api(user) + logs_last = Log.objects.filter(user=user.name).order_by('-start_time')[0:10] + logs_all = Log.objects.filter(user=user.name).order_by('-start_time') + logs_num = len(logs_all) + + return render_to_response('juser/user_detail.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def user_del(request): + user_id = request.GET.get('id', '') + if not user_id: + return HttpResponseRedirect('/juser/user_list/') + + if request.session.get('role_id', '') == '1': + if not validate(request, user=[user_id]): + return HttpResponseRedirect('/juser/user_list/') + + user = User.objects.filter(id=user_id) + if user and user[0].username != 'admin': + user = user[0] + user.delete() + server_del_user(user.username) + if LDAP_ENABLE: + ldap_del_user(user.username) + return HttpResponseRedirect('/juser/user_list/') + + +@require_admin +def user_del_ajax(request): + user_ids = request.POST.get('ids') + user_ids = user_ids.split(',') + if request.session.get('role_id', '') == 1: + if not validate(request, user=user_ids): + return "error" + for user_id in user_ids: + user = User.objects.filter(id=user_id) + if user and user[0].username != 'admin': + user = user[0] + user.delete() + server_del_user(user.username) + if LDAP_ENABLE: + ldap_del_user(user.username) + + return HttpResponse('删除成功') + + +@require_super_user +def user_edit(request): + header_title, path1, path2 = '编辑用户', '用户管理', '用户编辑' + if request.method == 'GET': + user_id = request.GET.get('id', '') + if not user_id: + return HttpResponseRedirect('/') + + user_role = {'SU': u'超级管理员', 'DA': u'部门管理员', 'CU': u'普通用户'} + user = User.objects.filter(id=user_id) + dept_all = DEPT.objects.all() + group_all = UserGroup.objects.all() + if user: + user = user[0] + groups_str = ' '.join([str(group.id) for group in user.group.all()]) + + else: + user_id = request.POST.get('user_id', '') + password = request.POST.get('password', '') + name = request.POST.get('name', '') + email = request.POST.get('email', '') + dept_id = request.POST.get('dept_id') + groups = request.POST.getlist('groups', []) + role_post = request.POST.get('role', 'CU') + ssh_key_pwd = request.POST.get('ssh_key_pwd', '') + is_active = True if request.POST.get('is_active', '1') == '1' else False + + user_role = {'SU': u'超级管理员', 'DA': u'部门管理员', 'CU': u'普通用户'} + dept = DEPT.objects.filter(id=dept_id) + if dept: + dept = dept[0] + else: + dept = DEPT.objects.get(id='2') + + if user_id: + user = User.objects.filter(id=user_id) + if user: + user = user[0] + else: + return HttpResponseRedirect('/juser/user_list/') + + if password != user.password: + password = md5_crypt(password) + + if ssh_key_pwd != user.ssh_key_pwd: + gen_ssh_key(user.username, ssh_key_pwd) + ssh_key_pwd = CRYPTOR.encrypt(ssh_key_pwd) + + db_update_user(user_id=user_id, + password=password, + name=name, + email=email, + groups=groups, + dept=dept, + role=role_post, + is_active=is_active, + ssh_key_pwd=ssh_key_pwd) + + return HttpResponseRedirect('/juser/user_list/') + + return render_to_response('juser/user_edit.html', locals(), context_instance=RequestContext(request)) + + +@require_admin +def user_edit_adm(request): + header_title, path1, path2 = '编辑用户', '用户管理', '用户编辑' + user, dept = get_session_user_dept(request) + if request.method == 'GET': + user_id = request.GET.get('id', '') + if not user_id: + return HttpResponseRedirect('/juser/user_list/') + + if not validate(request, user=[user_id]): + return HttpResponseRedirect('/juser/user_list/') + + user = User.objects.filter(id=user_id) + dept_all = DEPT.objects.all() + group_all = dept.usergroup_set.all() + if user: + user = user[0] + groups_str = ' '.join([str(group.id) for group in user.group.all()]) + + else: + user_id = request.POST.get('user_id', '') + password = request.POST.get('password', '') + name = request.POST.get('name', '') + email = request.POST.get('email', '') + groups = request.POST.getlist('groups', []) + ssh_key_pwd = request.POST.get('ssh_key_pwd', '') + is_active = True if request.POST.get('is_active', '1') == '1' else False + + if not validate(request, user=[user_id], user_group=groups): + return HttpResponseRedirect('/juser/user_edit/') + if user_id: + user = User.objects.filter(id=user_id) + if user: + user = user[0] + else: + return HttpResponseRedirect('/juser/user_list/') + + if password != user.password: + password = md5_crypt(password) + + if ssh_key_pwd != user.ssh_key_pwd: + ssh_key_pwd = CRYPTOR.encrypt(ssh_key_pwd) + + db_update_user(user_id=user_id, + password=password, + name=name, + email=email, + groups=groups, + is_active=is_active, + ssh_key_pwd=ssh_key_pwd) + + return HttpResponseRedirect('/juser/user_list/') + + return render_to_response('juser/user_edit.html', locals(), context_instance=RequestContext(request)) + + +def profile(request): + user_id = request.session.get('user_id') + if not user_id: + return HttpResponseRedirect('/') + user = User.objects.get(id=user_id) + return render_to_response('juser/profile.html', locals(), context_instance=RequestContext(request)) + + +def chg_info(request): + header_title, path1, path2 = '修改信息', '用户管理', '修改个人信息' + user_id = request.session.get('user_id') + user_set = User.objects.filter(id=user_id) + error = '' + if user_set: + user = user_set[0] + else: + return HttpResponseRedirect('/') + + if request.method == 'POST': + name = request.POST.get('name', '') + password = request.POST.get('password', '') + ssh_key_pwd = request.POST.get('ssh_key_pwd', '') + email = request.POST.get('email', '') + + if '' in [name, password, ssh_key_pwd, email]: + error = '不能为空' + + if len(password) < 6 or len(ssh_key_pwd) < 6: + error = '密码须大于6位' + + if not error: + if password != user.password: + password = md5_crypt(password) + + if ssh_key_pwd != user.ssh_key_pwd: + gen_ssh_key(user.username, ssh_key_pwd) + ssh_key_pwd = md5_crypt(ssh_key_pwd) + + user_set.update(name=name, password=password, ssh_key_pwd=ssh_key_pwd, email=email) + msg = '修改成功' + + return render_to_response('juser/chg_info.html', locals(), context_instance=RequestContext(request)) + + + + + +@require_login +def down_key(request): + user_id = '' + if is_super_user(request): + user_id = request.GET.get('id') + + if is_group_admin(request): + user_id = request.GET.get('id') + if not validate(request, user=[user_id]): + user_id = request.session.get('user_id') + + if is_common_user(request): + user_id = request.session.get('user_id') + + if user_id: + user = User.objects.filter(id=user_id) + if user: + user = user[0] + username = user.username + private_key_dir = os.path.join(BASE_DIR, 'keys/jumpserver/') + private_key_file = os.path.join(private_key_dir, username+".pem") + if os.path.isfile(private_key_file): + f = open(private_key_file) + data = f.read() + f.close() + response = HttpResponse(data, content_type='application/octet-stream') + response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(private_key_file) + return response + + return HttpResponse('No Key File. Contact Admin.') \ No newline at end of file diff --git a/keys/test b/keys/test deleted file mode 100644 index 0ae67e91e79d..000000000000 --- a/keys/test +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,D5AF0CC627FA8B85 - -oQLAgKLelCYNGc7cP51Bx3b66GmCKHAEhqBCsrPEi4eYKV7D30WOp+sdp8F5RaK1 -I/ZtGmv4jAaK4/KCBr2bGgH7cnkOhdj6T+ro9YVr92r5kD0gwHzYzbTCZP44N9Wn -83pUy4eUpMB659Y4TQgUAQVejyr1/ZZJSb8Kgah1xlLlM1ZSmK7PuqCSpBz16wil -TXrywWvsUhrAuAJh1NC7wr7mXm8tb2DMkT1+ckIQUqhOMJGEvgByI3SXUKR1c9lL -ZBh7RwukipvbujazxJxBvW50fLpdSDuBIxRsQhJ5PvYTV8BBwsp5KvbO5b/qkIOL -RUxY4q3o7fHtXiRf4vD9iD1U7F39UMnDIie6jk642oN4aYmvyc0SnVH8RcVarnCA -HkdZ/5c93BCZRovay6DoIumN/OmURe83A9hzsHnMg9hkLAapw5dmlsvtk307YWK8 -YnAy7TMLS72RdAxSJHXN9U+U7QKDu47jiIkST3kwNLXYm4gvY7eFlg82Ux2h9Soh -R5qJ6pdYh1Ah/msbE9v/HkWCqhU6fD38MaAmcuCAoOh2LuI+32+2ZkCT04hPhzQL -AjfrMsUFKiH/+IrFtQ8CcwaFtVR9b/Ebe65SQuBXV3Bcrcx91MWKBjCpiB1rQQZ/ -mxNh4jQmvUOJYhDv8D1TZMCLrAREt07uPLhL24klv6v4lf204xbLhdYA1kW/m/16 -+oEH6CHMo8qVqWylATfya1Iv+htAXs6Pi65j6QQjyM/sQZ+Cn0enGSS5S9WIx+Ca -C+kbRBmxfwYXROu7NkmWexiU3a7VmTj/0yA8uRXY7jbEyGgupXiAeXa2/pRX2XRo -8MugyIoZzLxvkszQ90WxH/9hO+eNDY1Wo+ONo8deos3pogjeIPhiFQlx2EFowGcf -TcNFgluQliwVm5qEWe2SWoNlHgnI7rhus1yAexH/G2uJHpd8eid3Rn19Fh1TxD16 -r/+I6TEp7u27Fc9T+HVXg46kXxf7+p0/fcHLxOk0A5wfLzQgB6fVvXoXoldWoomr -FXpKmDTDjTp15R1pVZ3eVtuJp3wA+N6YsL7F2NsmtKMaMrXuMwSwJUJPpFSD/DXe -BUcqSeQMwvwSgzH4qkBtJcQ6baEVgBvDeRKoVInZ9D7FpumTv5tSnsqyD0NBZsXC -qmA5Sk+w2CRW1Nbi/uSFdDACZo8iDhILJ9fHRtNLyB+BN2cN7dIQZlmOQxK3omqd -iCgu1q31iE8wgxzEnrtPxLWi/2jr7WX0NVFzE6Qjjpvqa+3k4MjNDeNfPKHJMK50 -o8hf4jlSZxhjc4D+U9ksSJZOl6NyuLhpp8YlVSkZ/Oiz6U1reTf8qZUOkBgY5V2T -0N+Pwqs81nA4Hsh32MxuVIt0RLtp2uLUyeEHatEp3akABFvWWMWbxgbwsmOXtnsj -QxJQ6jL+CCvpufu34prkMeKPApqTrwHq9YLNBFgg4ts+pl8wHrFo1CFma2ljvFzq -8FNn8FDJcebasNmnJOvXTryqp/Qd85fKH0XuR100azmXnuRmxuDmNXfN/ejtne1b -ZyDrSEGOlr/GpxTLDtbSSu82I+XqvAicXsUqbOqWUPM2mAKtDVfaIQ== ------END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/log_handler.py b/log_handler.py new file mode 100644 index 000000000000..0d8b91e774ba --- /dev/null +++ b/log_handler.py @@ -0,0 +1,84 @@ +#!/usr/bin/python +# coding: utf-8 + +import os +import re +import time +import psutil +from datetime import datetime + +os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings' + +import django +django.setup() +from jlog.models import Log + + +def log_hanler(id): + log = Log.objects.get(id=id) + pattern = re.compile(r'([\[.*@.*\][\$#].*)|(.*mysql>.*)') + if log: + filename = log.log_path + if os.path.isfile(filename): + f_his = filename + '.his' + f1 = open(filename) + f2 = open(f_his, 'a') + lines = f1.readlines() + for line in lines[7:]: + match = pattern.match(line) + if match: + newline = re.sub('\[[A-Z]', '', line) + f2.write(newline) + f1.close() + f2.close() + log.log_finished = True + log.save() + + +def set_finish(id): + log = Log.objects.filter(id=id) + if log: + log.update(is_finished=1, end_time=datetime.now()) + + +def kill_pid(pid): + try: + os.kill(pid, 9) + except OSError: + pass + + +def get_pids(): + pids1, pids2 = [], [] + pids1_obj = Log.objects.filter(is_finished=0) + pids2_obj = Log.objects.filter(is_finished=1, log_finished=0) + for pid_obj in pids1_obj: + pids1.append((pid_obj.id, pid_obj.pid, pid_obj.log_path, pid_obj.is_finished, pid_obj.log_finished, pid_obj.start_time)) + for pid_obj in pids2_obj: + pids2.append(pid_obj.id) + + return pids1, pids2 + + +def run(): + pids1, pids2 = get_pids() + for pid_id in pids2: + log_hanler(pid_id) + + for pid_id, pid, log_path, is_finished, log_finished, start_time in pids1: + print pid_id, start_time, type(start_time) + try: + file_time = int(os.stat(log_path).st_ctime) + now_time = int(time.time()) + if now_time - file_time > 18000: + if psutil.pid_exists(pid): + kill_pid(pid) + set_finish(pid_id) + log_hanler(pid_id) + except OSError: + pass + +if __name__ == '__main__': + while True: + run() + time.sleep(5) diff --git a/logs/test.log b/logs/test.log deleted file mode 100755 index e69de29bb2d1..000000000000 diff --git a/webroot/AutoSa/manage.py b/manage.py old mode 100755 new mode 100644 similarity index 70% rename from webroot/AutoSa/manage.py rename to manage.py index b9e26787acac..f72e2bc4a9b4 --- a/webroot/AutoSa/manage.py +++ b/manage.py @@ -3,7 +3,7 @@ import sys if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "AutoSa.settings") + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "jumpserver.settings") from django.core.management import execute_from_command_line diff --git a/runserver b/runserver deleted file mode 100755 index 9a5211734a7d..000000000000 --- a/runserver +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -manage_file="./webroot/AutoSa/manage.py" -log_handler_file="./webroot/AutoSa/log_handler.py" -websocket_file="./webroot/AutoSa/websocket/index.js" - -which node &> /dev/null -if [ $? != '0' ];then - echo "Please define the node.js binary file 'node' in the PATH." - exit -fi -node $websocket_file & -if [ -f $manage_file -a -e $manage_file ] && [ -f $log_handler_file -a -e $log_handler_file ];then - sudo $manage_file runserver 0.0.0.0:80 &> logs/access.log & - $log_handler_file &> logs/handler.log & -else - echo "manage.py or log_handler.py isn't exist or executable." -fi diff --git a/scripts/jumpserver.sh b/scripts/jumpserver.sh deleted file mode 100644 index b59520a03753..000000000000 --- a/scripts/jumpserver.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -if [ $USER == 'admin' ] || [ $USER == 'root' ];then - echo "" -else - python /opt/jumpserver/jumpserver.py - if [ $USER == 'guanghongwei' ];then - echo - else - exit 3 - echo - fi -fi diff --git a/service.sh b/service.sh new file mode 100644 index 000000000000..fbac87af4eeb --- /dev/null +++ b/service.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Date: 2015-04-12 +# Version: 2.0.0 +# Site: http://www.jumpserver.org +# Author: jumpserver group + +. /etc/init.d/functions +export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/node/bin + +base_dir=$(dirname $0) + +case $1 in +start) + daemon $base_dir/manage.py runserver 0.0.0.0:80 & + daemon $base_dir/log_handler.py & + cd $base_dir/websocket/; daemon node index.js & + ;; + +stop) + pkill -15 python + pkill -15 node + ;; + +esac diff --git a/ssh b/ssh new file mode 100644 index 000000000000..173fd36678ff --- /dev/null +++ b/ssh @@ -0,0 +1,395 @@ +#!/usr/local/bin/python + +import socket +import sys +import os +import ast +import select +import time +from datetime import datetime +import paramiko +import struct +import fcntl +import signal +import textwrap +import django +import getpass +import fnmatch +import optparse +import readline +from multiprocessing import Pool +from ConfigParser import ConfigParser +from django.core.exceptions import ObjectDoesNotExist + +os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings' +django.setup() +from juser.models import User +from jasset.models import Asset +from jlog.models import Log +from jumpserver.views import PyCrypt +from jumpserver.api import user_perm_asset_api, user_perm_group_api + +try: + import termios + import tty +except ImportError: + print '\033[1;31mOnly postfix supported.\033[0m' + time.sleep(3) + sys.exit() + +BASE_DIR = os.path.abspath(os.path.dirname(__file__)) +CONF = ConfigParser() +CONF.read(os.path.join(BASE_DIR, 'jumpserver.conf')) +LOG_DIR = os.path.join(BASE_DIR, 'logs') +SSH_KEY_DIR = os.path.join(BASE_DIR, 'keys') +SERVER_KEY_DIR = os.path.join(SSH_KEY_DIR, 'server') +KEY = CONF.get('web', 'key') +LOGIN_NAME = getpass.getuser() + + +def color_print(msg, color='blue'): + """Print colorful string.""" + color_msg = {'blue': '\033[1;36m%s\033[0m', + 'green': '\033[1;32m%s\033[0m', + 'red': '\033[1;31m%s\033[0m'} + + print color_msg.get(color, 'blue') % msg + + +def color_print_exit(msg, color='red'): + """Print colorful string and exit.""" + color_print(msg, color=color) + time.sleep(2) + sys.exit() + + +class ServerError(Exception): + pass + + +def get_win_size(): + """This function use to get the size of the windows!""" + if 'TIOCGWINSZ' in dir(termios): + TIOCGWINSZ = termios.TIOCGWINSZ + else: + TIOCGWINSZ = 1074295912L # Assume + s = struct.pack('HHHH', 0, 0, 0, 0) + x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s) + return struct.unpack('HHHH', x)[0:2] + + +def set_win_size(sig, data): + """This function use to set the window size of the terminal!""" + try: + win_size = get_win_size() + channel.resize_pty(height=win_size[0], width=win_size[1]) + except: + pass + + +def get_object(model, **kwargs): + try: + the_object = model.objects.get(**kwargs) + except ObjectDoesNotExist: + raise ServerError('Object get %s failed.' % str(kwargs.values())) + return the_object + + +def log_record(username, host): + """Logging user command and output.""" + connect_log_dir = os.path.join(LOG_DIR, 'connect') + timestamp_start = int(time.time()) + today = time.strftime('%Y%m%d', time.localtime(timestamp_start)) + time_now = time.strftime('%H%M%S', time.localtime(timestamp_start)) + today_connect_log_dir = os.path.join(connect_log_dir, today) + log_filename = '%s_%s_%s.log' % (username, host, time_now) + log_file_path = os.path.join(today_connect_log_dir, log_filename) + pid = os.getpid() + ip_list = [] + remote_ip = os.popen("who |grep `ps aux |gawk '{if ($2==%s) print $1}'` |gawk '{print $5}'|tr -d '()'" % pid).readlines() + for ip in remote_ip: + ip_list.append(ip.strip('\n')) + ip_list = ','.join(list(set(ip_list))) + + if not os.path.isdir(today_connect_log_dir): + try: + os.makedirs(today_connect_log_dir) + os.chmod(today_connect_log_dir, 0777) + except OSError: + raise ServerError('Create %s failed, Please modify %s permission.' % (today_connect_log_dir, connect_log_dir)) + + try: + log_file = open(log_file_path, 'a') + except IOError: + raise ServerError('Create logfile failed, Please modify %s permission.' % today_connect_log_dir) + + log = Log(user=username, host=host, remote_ip=ip_list, log_path=log_file_path, start_time=datetime.now(), pid=pid) + log_file.write('Starttime is %s\n' % datetime.now()) + log.save() + return log_file, log + + +def posix_shell(chan, username, host): + """ + Use paramiko channel connect server interactive. + """ + log_file, log = log_record(username, host) + old_tty = termios.tcgetattr(sys.stdin) + try: + tty.setraw(sys.stdin.fileno()) + tty.setcbreak(sys.stdin.fileno()) + chan.settimeout(0.0) + + while True: + try: + r, w, e = select.select([chan, sys.stdin], [], []) + except: + pass + + if chan in r: + try: + x = chan.recv(1024) + if len(x) == 0: + break + sys.stdout.write(x) + sys.stdout.flush() + log_file.write(x) + log_file.flush() + except socket.timeout: + pass + + if sys.stdin in r: + x = os.read(sys.stdin.fileno(), 1) + if len(x) == 0: + break + chan.send(x) + + finally: + timestamp_end = time.time() + termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty) + log_file.write('Endtime is %s' % datetime.now()) + log_file.close() + log.is_finished = True + log.log_finished = False + log.end_time = datetime.now() + log.save() + + +def get_user_host(username): + """Get the hosts of under the user control.""" + hosts_attr = {} + asset_all = user_perm_asset_api(username) + for asset in asset_all: + hosts_attr[asset.ip] = [asset.id, asset.comment] + return hosts_attr + + +def get_user_hostgroup(username): + """Get the hostgroups of under the user control.""" + groups_attr = {} + group_all = user_perm_group_api(username) + for group in group_all: + groups_attr[group.name] = [group.id, group.comment] + return groups_attr + + +def get_connect_item(username, ip): + cryptor = PyCrypt(KEY) + + asset = get_object(Asset, ip=ip) + port = asset.port + + if not asset.is_active: + raise ServerError('Host %s is not active.' % ip) + + user = get_object(User, username=username) + + if not user.is_active: + raise ServerError('User %s is not active.' % username) + + login_type_dict = { + 'L': user.ldap_pwd, + } + + if asset.login_type in login_type_dict: + password = cryptor.decrypt(login_type_dict[asset.login_type]) + return username, password, ip, port + + elif asset.login_type == 'M': + username = asset.username + password = cryptor.decrypt(asset.password) + return username, password, ip, port + + else: + raise ServerError('Login type is not in ["L", "M"]') + + +def verify_connect(username, part_ip): + hosts_attr = get_user_host(username) + hosts = hosts_attr.keys() + ip_matched = [ip for ip in hosts if part_ip in ip] + + if len(ip_matched) > 1: + for ip in ip_matched: + print '%s -- %s' % (ip, hosts_attr[ip][1]) + elif len(ip_matched) < 1: + color_print('No Permission or No host.', 'red') + else: + username, password, host, port = get_connect_item(username, ip_matched[0]) + print username, password, host, port + connect(username, password, host, port, LOGIN_NAME) + + +def print_prompt(): + msg = """\033[1;32m### Welcome Use JumpServer To Login. ### \033[0m + 1) Type \033[32mIP ADDRESS\033[0m To Login. + 2) Type \033[32mP/p\033[0m To Print The Servers You Available. + 3) Type \033[32mG/g\033[0m To Print The Server Groups You Available. + 4) Type \033[32mE/e\033[0m To Execute Command On Several Servers. + 5) Type \033[32mQ/q\033[0m To Quit. + """ + print textwrap.dedent(msg) + + +def print_user_host(username): + hosts_attr = get_user_host(username) + hosts = hosts_attr.keys() + hosts.sort() + for ip in hosts: + print '%s -- %s' % (ip, hosts_attr[ip][1]) + + +def print_user_hostgroup(username): + group_attr = get_user_hostgroup(username) + groups = group_attr.keys() + for g in groups: + print '%s -- %s' % (g, group_attr[g][1]) + + +def connect(username, password, host, port, login_name): + """ + Connect server. + """ + ps1 = "PS1='[\u@%s \W]\$ '\n" % host + login_msg = "clear;echo -e '\\033[32mLogin %s done. Enjoy it.\\033[0m'\n" % host + + # Make a ssh connection + ssh = paramiko.SSHClient() + ssh.load_system_host_keys() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + try: + ssh.connect(host, port=port, username=username, password=password, compress=True) + except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException: + raise ServerError('Authentication Error.') + except socket.error: + raise ServerError('Connect SSH Socket Port Error, Please Correct it.') + + # Make a channel and set windows size + global channel + win_size = get_win_size() + channel = ssh.invoke_shell(height=win_size[0], width=win_size[1]) + #channel.resize_pty(height=win_size[0], width=win_size[1]) + try: + signal.signal(signal.SIGWINCH, set_win_size) + except: + pass + + # Set PS1 and msg it + channel.send(ps1) + channel.send(login_msg) + + # Make ssh interactive tunnel + posix_shell(channel, login_name, host) + + # Shutdown channel socket + channel.close() + ssh.close() + + +def remote_exec_cmd(ip, port, username, password, cmd): + try: + time.sleep(5) + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect(ip, port, username, password, timeout=5) + stdin, stdout, stderr = ssh.exec_command("bash -l -c '%s'" % cmd) + out = stdout.readlines() + err = stderr.readlines() + color_print('%s:' %ip, 'blue') + for i in out: + color_print(" " * 4 + i.strip(), 'green') + for j in err: + color_print(" " * 4 + j.strip(), 'red') + ssh.close() + except Exception as e: + color_print(ip + ':', 'blue') + color_print(str(e), 'red') + + +def multi_remote_exec_cmd(hosts, username, cmd): + pool = Pool(processes=5) + for host in hosts: + username, password, ip, port = get_connect_item(username, host) + pool.apply_async(remote_exec_cmd, (ip, port, username, password, cmd)) + pool.close() + pool.join() + + +def exec_cmd_servers(username): + hosts = [] + color_print("Input the Host IP(s),Separated by Commas, q/Q to Quit.\n \ + You can choose in the following IP(s), Use Linux / Unix glob.", 'green') + print_user_host(LOGIN_NAME) + while True: + inputs = raw_input('\033[1;32mip(s)>: \033[0m') + if inputs in ['q', 'Q']: + break + get_hosts = get_user_host(username).keys() + for host in get_hosts: + if fnmatch.fnmatch(host, inputs): + hosts.append(host.strip()) + if len(hosts) == 0: + color_print("Check again, Not matched any ip!", 'red') + continue + else: + print "You matched ip: %s" % hosts + color_print("Input the Command , The command will be Execute on servers, q/Q to quit.", 'green') + while True: + cmd = raw_input('\033[1;32mCmd(s): \033[0m') + if cmd in ['q', 'Q']: + break + exec_log_dir = os.path.join(LOG_DIR, 'exec_cmds') + if not os.path.isdir(exec_log_dir): + os.mkdir(exec_log_dir) + os.chmod(exec_log_dir, 0777) + filename = "%s/%s.log" % (exec_log_dir, time.strftime('%Y%m%d')) + f = open(filename, 'a') + f.write("DateTime: %s User: %s Host: %s Cmds: %s\n" % + (time.strftime('%Y/%m/%d %H:%M:%S'), username, hosts, cmd)) + multi_remote_exec_cmd(hosts, username, cmd) + + +def help(): + global p, options, arguments + usage = "usage: %prog '' [options] arg1 [options] arg2" + p = optparse.OptionParser(usage=usage) + p.add_option('-p', '--host', help = "Print The Servers You Available.") + p.add_option('-g', '--group', help = "Print The Server Groups You Available.") + options, arguments = p.parse_args() + + +def main(): + help() + if options.host: + pass + elif options.group: + pass + else: + try: + verify_connect(LOGIN_NAME, sys.argv[1]) + except ServerError, e: + color_print(e, 'red') + + +if __name__ == '__main__': + main() diff --git a/ssh.py b/ssh.py new file mode 100644 index 000000000000..57836735bc73 --- /dev/null +++ b/ssh.py @@ -0,0 +1,395 @@ +#!/usr/bin/env python + +import socket +import sys +import os +import ast +import select +import time +from datetime import datetime +import paramiko +import struct +import fcntl +import signal +import textwrap +import django +import getpass +import fnmatch +import optparse +import readline +from multiprocessing import Pool +from ConfigParser import ConfigParser +from django.core.exceptions import ObjectDoesNotExist + +os.environ['DJANGO_SETTINGS_MODULE'] = 'jumpserver.settings' +django.setup() +from juser.models import User +from jasset.models import Asset +from jlog.models import Log +from jumpserver.views import PyCrypt +from jumpserver.api import user_perm_asset_api, user_perm_group_api + +try: + import termios + import tty +except ImportError: + print '\033[1;31mOnly postfix supported.\033[0m' + time.sleep(3) + sys.exit() + +BASE_DIR = os.path.abspath(os.path.dirname(__file__)) +CONF = ConfigParser() +CONF.read(os.path.join(BASE_DIR, 'jumpserver.conf')) +LOG_DIR = os.path.join(BASE_DIR, 'logs') +SSH_KEY_DIR = os.path.join(BASE_DIR, 'keys') +SERVER_KEY_DIR = os.path.join(SSH_KEY_DIR, 'server') +KEY = CONF.get('web', 'key') +LOGIN_NAME = getpass.getuser() + + +def color_print(msg, color='blue'): + """Print colorful string.""" + color_msg = {'blue': '\033[1;36m%s\033[0m', + 'green': '\033[1;32m%s\033[0m', + 'red': '\033[1;31m%s\033[0m'} + + print color_msg.get(color, 'blue') % msg + + +def color_print_exit(msg, color='red'): + """Print colorful string and exit.""" + color_print(msg, color=color) + time.sleep(2) + sys.exit() + + +class ServerError(Exception): + pass + + +def get_win_size(): + """This function use to get the size of the windows!""" + if 'TIOCGWINSZ' in dir(termios): + TIOCGWINSZ = termios.TIOCGWINSZ + else: + TIOCGWINSZ = 1074295912L # Assume + s = struct.pack('HHHH', 0, 0, 0, 0) + x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s) + return struct.unpack('HHHH', x)[0:2] + + +def set_win_size(sig, data): + """This function use to set the window size of the terminal!""" + try: + win_size = get_win_size() + channel.resize_pty(height=win_size[0], width=win_size[1]) + except: + pass + + +def get_object(model, **kwargs): + try: + the_object = model.objects.get(**kwargs) + except ObjectDoesNotExist: + raise ServerError('Object get %s failed.' % str(kwargs.values())) + return the_object + + +def log_record(username, host): + """Logging user command and output.""" + connect_log_dir = os.path.join(LOG_DIR, 'connect') + timestamp_start = int(time.time()) + today = time.strftime('%Y%m%d', time.localtime(timestamp_start)) + time_now = time.strftime('%H%M%S', time.localtime(timestamp_start)) + today_connect_log_dir = os.path.join(connect_log_dir, today) + log_filename = '%s_%s_%s.log' % (username, host, time_now) + log_file_path = os.path.join(today_connect_log_dir, log_filename) + pid = os.getpid() + ip_list = [] + remote_ip = os.popen("who |grep `ps aux |gawk '{if ($2==%s) print $1}'` |gawk '{print $5}'|tr -d '()'" % pid).readlines() + for ip in remote_ip: + ip_list.append(ip.strip('\n')) + ip_list = ','.join(list(set(ip_list))) + + if not os.path.isdir(today_connect_log_dir): + try: + os.makedirs(today_connect_log_dir) + os.chmod(today_connect_log_dir, 0777) + except OSError: + raise ServerError('Create %s failed, Please modify %s permission.' % (today_connect_log_dir, connect_log_dir)) + + try: + log_file = open(log_file_path, 'a') + except IOError: + raise ServerError('Create logfile failed, Please modify %s permission.' % today_connect_log_dir) + + log = Log(user=username, host=host, remote_ip=ip_list, log_path=log_file_path, start_time=datetime.now(), pid=pid) + log_file.write('Starttime is %s\n' % datetime.now()) + log.save() + return log_file, log + + +def posix_shell(chan, username, host): + """ + Use paramiko channel connect server interactive. + """ + log_file, log = log_record(username, host) + old_tty = termios.tcgetattr(sys.stdin) + try: + tty.setraw(sys.stdin.fileno()) + tty.setcbreak(sys.stdin.fileno()) + chan.settimeout(0.0) + + while True: + try: + r, w, e = select.select([chan, sys.stdin], [], []) + except: + pass + + if chan in r: + try: + x = chan.recv(1024) + if len(x) == 0: + break + sys.stdout.write(x) + sys.stdout.flush() + log_file.write(x) + log_file.flush() + except socket.timeout: + pass + + if sys.stdin in r: + x = os.read(sys.stdin.fileno(), 1) + if len(x) == 0: + break + chan.send(x) + + finally: + timestamp_end = time.time() + termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty) + log_file.write('Endtime is %s' % datetime.now()) + log_file.close() + log.is_finished = True + log.log_finished = False + log.end_time = datetime.now() + log.save() + + +def get_user_host(username): + """Get the hosts of under the user control.""" + hosts_attr = {} + asset_all = user_perm_asset_api(username) + for asset in asset_all: + hosts_attr[asset.ip] = [asset.id, asset.comment] + return hosts_attr + + +def get_user_hostgroup(username): + """Get the hostgroups of under the user control.""" + groups_attr = {} + group_all = user_perm_group_api(username) + for group in group_all: + groups_attr[group.name] = [group.id, group.comment] + return groups_attr + + +def get_connect_item(username, ip): + cryptor = PyCrypt(KEY) + + asset = get_object(Asset, ip=ip) + port = asset.port + + if not asset.is_active: + raise ServerError('Host %s is not active.' % ip) + + user = get_object(User, username=username) + + if not user.is_active: + raise ServerError('User %s is not active.' % username) + + login_type_dict = { + 'L': user.ldap_pwd, + } + + if asset.login_type in login_type_dict: + password = cryptor.decrypt(login_type_dict[asset.login_type]) + return username, password, ip, port + + elif asset.login_type == 'M': + username = asset.username + password = cryptor.decrypt(asset.password) + return username, password, ip, port + + else: + raise ServerError('Login type is not in ["L", "M"]') + + +def verify_connect(username, part_ip): + hosts_attr = get_user_host(username) + hosts = hosts_attr.keys() + ip_matched = [ip for ip in hosts if part_ip in ip] + + if len(ip_matched) > 1: + for ip in ip_matched: + print '%s -- %s' % (ip, hosts_attr[ip][1]) + elif len(ip_matched) < 1: + color_print('No Permission or No host.', 'red') + else: + username, password, host, port = get_connect_item(username, ip_matched[0]) + print username, password, host, port + connect(username, password, host, port, LOGIN_NAME) + + +def print_prompt(): + msg = """\033[1;32m### Welcome Use JumpServer To Login. ### \033[0m + 1) Type \033[32mIP ADDRESS\033[0m To Login. + 2) Type \033[32mP/p\033[0m To Print The Servers You Available. + 3) Type \033[32mG/g\033[0m To Print The Server Groups You Available. + 4) Type \033[32mE/e\033[0m To Execute Command On Several Servers. + 5) Type \033[32mQ/q\033[0m To Quit. + """ + print textwrap.dedent(msg) + + +def print_user_host(username): + hosts_attr = get_user_host(username) + hosts = hosts_attr.keys() + hosts.sort() + for ip in hosts: + print '%s -- %s' % (ip, hosts_attr[ip][1]) + + +def print_user_hostgroup(username): + group_attr = get_user_hostgroup(username) + groups = group_attr.keys() + for g in groups: + print '%s -- %s' % (g, group_attr[g][1]) + + +def connect(username, password, host, port, login_name): + """ + Connect server. + """ + ps1 = "PS1='[\u@%s \W]\$ '\n" % host + login_msg = "clear;echo -e '\\033[32mLogin %s done. Enjoy it.\\033[0m'\n" % host + + # Make a ssh connection + ssh = paramiko.SSHClient() + ssh.load_system_host_keys() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + try: + ssh.connect(host, port=port, username=username, password=password, compress=True) + except paramiko.ssh_exception.AuthenticationException, paramiko.ssh_exception.SSHException: + raise ServerError('Authentication Error.') + except socket.error: + raise ServerError('Connect SSH Socket Port Error, Please Correct it.') + + # Make a channel and set windows size + global channel + win_size = get_win_size() + channel = ssh.invoke_shell(height=win_size[0], width=win_size[1]) + #channel.resize_pty(height=win_size[0], width=win_size[1]) + try: + signal.signal(signal.SIGWINCH, set_win_size) + except: + pass + + # Set PS1 and msg it + channel.send(ps1) + channel.send(login_msg) + + # Make ssh interactive tunnel + posix_shell(channel, login_name, host) + + # Shutdown channel socket + channel.close() + ssh.close() + + +def remote_exec_cmd(ip, port, username, password, cmd): + try: + time.sleep(5) + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect(ip, port, username, password, timeout=5) + stdin, stdout, stderr = ssh.exec_command("bash -l -c '%s'" % cmd) + out = stdout.readlines() + err = stderr.readlines() + color_print('%s:' %ip, 'blue') + for i in out: + color_print(" " * 4 + i.strip(), 'green') + for j in err: + color_print(" " * 4 + j.strip(), 'red') + ssh.close() + except Exception as e: + color_print(ip + ':', 'blue') + color_print(str(e), 'red') + + +def multi_remote_exec_cmd(hosts, username, cmd): + pool = Pool(processes=5) + for host in hosts: + username, password, ip, port = get_connect_item(username, host) + pool.apply_async(remote_exec_cmd, (ip, port, username, password, cmd)) + pool.close() + pool.join() + + +def exec_cmd_servers(username): + hosts = [] + color_print("Input the Host IP(s),Separated by Commas, q/Q to Quit.\n \ + You can choose in the following IP(s), Use Linux / Unix glob.", 'green') + print_user_host(LOGIN_NAME) + while True: + inputs = raw_input('\033[1;32mip(s)>: \033[0m') + if inputs in ['q', 'Q']: + break + get_hosts = get_user_host(username).keys() + for host in get_hosts: + if fnmatch.fnmatch(host, inputs): + hosts.append(host.strip()) + if len(hosts) == 0: + color_print("Check again, Not matched any ip!", 'red') + continue + else: + print "You matched ip: %s" % hosts + color_print("Input the Command , The command will be Execute on servers, q/Q to quit.", 'green') + while True: + cmd = raw_input('\033[1;32mCmd(s): \033[0m') + if cmd in ['q', 'Q']: + break + exec_log_dir = os.path.join(LOG_DIR, 'exec_cmds') + if not os.path.isdir(exec_log_dir): + os.mkdir(exec_log_dir) + os.chmod(exec_log_dir, 0777) + filename = "%s/%s.log" % (exec_log_dir, time.strftime('%Y%m%d')) + f = open(filename, 'a') + f.write("DateTime: %s User: %s Host: %s Cmds: %s\n" % + (time.strftime('%Y/%m/%d %H:%M:%S'), username, hosts, cmd)) + multi_remote_exec_cmd(hosts, username, cmd) + + +def help(): + global p, options, arguments + usage = "usage: %prog '' [options] arg1 [options] arg2" + p = optparse.OptionParser(usage=usage) + p.add_option('-p', '--host', help = "Print The Servers You Available.") + p.add_option('-g', '--group', help = "Print The Server Groups You Available.") + options, arguments = p.parse_args() + + +def main(): + help() + if options.host: + pass + elif options.group: + pass + else: + try: + verify_connect(LOGIN_NAME, sys.argv[1]) + except ServerError, e: + color_print(e, 'red') + + +if __name__ == '__main__': + main() diff --git a/static/css/animate.css b/static/css/animate.css new file mode 100644 index 000000000000..0f9fba11e232 --- /dev/null +++ b/static/css/animate.css @@ -0,0 +1,2848 @@ +@charset "UTF-8"; + +/*! +Animate.css - http://daneden.me/animate +Licensed under the MIT license + +Copyright (c) 2013 Daniel Eden + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +.animated { + -webkit-animation-duration: 1s; + animation-duration: 1s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + z-index: 100; +} + +.animated.infinite { + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; +} + +.animated.hinge { + -webkit-animation-duration: 2s; + animation-duration: 2s; +} + +@-webkit-keyframes bounce { + 0%, 20%, 50%, 80%, 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 40% { + -webkit-transform: translateY(-30px); + transform: translateY(-30px); + } + + 60% { + -webkit-transform: translateY(-15px); + transform: translateY(-15px); + } +} + +@keyframes bounce { + 0%, 20%, 50%, 80%, 100% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 40% { + -webkit-transform: translateY(-30px); + -ms-transform: translateY(-30px); + transform: translateY(-30px); + } + + 60% { + -webkit-transform: translateY(-15px); + -ms-transform: translateY(-15px); + transform: translateY(-15px); + } +} + +.bounce { + -webkit-animation-name: bounce; + animation-name: bounce; +} + +@-webkit-keyframes flash { + 0%, 50%, 100% { + opacity: 1; + } + + 25%, 75% { + opacity: 0; + } +} + +@keyframes flash { + 0%, 50%, 100% { + opacity: 1; + } + + 25%, 75% { + opacity: 0; + } +} + +.flash { + -webkit-animation-name: flash; + animation-name: flash; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes pulse { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + } + + 50% { + -webkit-transform: scale(1.1); + transform: scale(1.1); + } + + 100% { + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@keyframes pulse { + 0% { + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + } + + 50% { + -webkit-transform: scale(1.1); + -ms-transform: scale(1.1); + transform: scale(1.1); + } + + 100% { + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + } +} + +.pulse { + -webkit-animation-name: pulse; + animation-name: pulse; +} + +@-webkit-keyframes rubberBand { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + } + + 30% { + -webkit-transform: scaleX(1.25) scaleY(0.75); + transform: scaleX(1.25) scaleY(0.75); + } + + 40% { + -webkit-transform: scaleX(0.75) scaleY(1.25); + transform: scaleX(0.75) scaleY(1.25); + } + + 60% { + -webkit-transform: scaleX(1.15) scaleY(0.85); + transform: scaleX(1.15) scaleY(0.85); + } + + 100% { + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@keyframes rubberBand { + 0% { + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + } + + 30% { + -webkit-transform: scaleX(1.25) scaleY(0.75); + -ms-transform: scaleX(1.25) scaleY(0.75); + transform: scaleX(1.25) scaleY(0.75); + } + + 40% { + -webkit-transform: scaleX(0.75) scaleY(1.25); + -ms-transform: scaleX(0.75) scaleY(1.25); + transform: scaleX(0.75) scaleY(1.25); + } + + 60% { + -webkit-transform: scaleX(1.15) scaleY(0.85); + -ms-transform: scaleX(1.15) scaleY(0.85); + transform: scaleX(1.15) scaleY(0.85); + } + + 100% { + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + } +} + +.rubberBand { + -webkit-animation-name: rubberBand; + animation-name: rubberBand; +} + +@-webkit-keyframes shake { + 0%, 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 10%, 30%, 50%, 70%, 90% { + -webkit-transform: translateX(-10px); + transform: translateX(-10px); + } + + 20%, 40%, 60%, 80% { + -webkit-transform: translateX(10px); + transform: translateX(10px); + } +} + +@keyframes shake { + 0%, 100% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 10%, 30%, 50%, 70%, 90% { + -webkit-transform: translateX(-10px); + -ms-transform: translateX(-10px); + transform: translateX(-10px); + } + + 20%, 40%, 60%, 80% { + -webkit-transform: translateX(10px); + -ms-transform: translateX(10px); + transform: translateX(10px); + } +} + +.shake { + -webkit-animation-name: shake; + animation-name: shake; +} + +@-webkit-keyframes swing { + 20% { + -webkit-transform: rotate(15deg); + transform: rotate(15deg); + } + + 40% { + -webkit-transform: rotate(-10deg); + transform: rotate(-10deg); + } + + 60% { + -webkit-transform: rotate(5deg); + transform: rotate(5deg); + } + + 80% { + -webkit-transform: rotate(-5deg); + transform: rotate(-5deg); + } + + 100% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } +} + +@keyframes swing { + 20% { + -webkit-transform: rotate(15deg); + -ms-transform: rotate(15deg); + transform: rotate(15deg); + } + + 40% { + -webkit-transform: rotate(-10deg); + -ms-transform: rotate(-10deg); + transform: rotate(-10deg); + } + + 60% { + -webkit-transform: rotate(5deg); + -ms-transform: rotate(5deg); + transform: rotate(5deg); + } + + 80% { + -webkit-transform: rotate(-5deg); + -ms-transform: rotate(-5deg); + transform: rotate(-5deg); + } + + 100% { + -webkit-transform: rotate(0deg); + -ms-transform: rotate(0deg); + transform: rotate(0deg); + } +} + +.swing { + -webkit-transform-origin: top center; + -ms-transform-origin: top center; + transform-origin: top center; + -webkit-animation-name: swing; + animation-name: swing; +} + +@-webkit-keyframes tada { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + } + + 10%, 20% { + -webkit-transform: scale(0.9) rotate(-3deg); + transform: scale(0.9) rotate(-3deg); + } + + 30%, 50%, 70%, 90% { + -webkit-transform: scale(1.1) rotate(3deg); + transform: scale(1.1) rotate(3deg); + } + + 40%, 60%, 80% { + -webkit-transform: scale(1.1) rotate(-3deg); + transform: scale(1.1) rotate(-3deg); + } + + 100% { + -webkit-transform: scale(1) rotate(0); + transform: scale(1) rotate(0); + } +} + +@keyframes tada { + 0% { + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + } + + 10%, 20% { + -webkit-transform: scale(0.9) rotate(-3deg); + -ms-transform: scale(0.9) rotate(-3deg); + transform: scale(0.9) rotate(-3deg); + } + + 30%, 50%, 70%, 90% { + -webkit-transform: scale(1.1) rotate(3deg); + -ms-transform: scale(1.1) rotate(3deg); + transform: scale(1.1) rotate(3deg); + } + + 40%, 60%, 80% { + -webkit-transform: scale(1.1) rotate(-3deg); + -ms-transform: scale(1.1) rotate(-3deg); + transform: scale(1.1) rotate(-3deg); + } + + 100% { + -webkit-transform: scale(1) rotate(0); + -ms-transform: scale(1) rotate(0); + transform: scale(1) rotate(0); + } +} + +.tada { + -webkit-animation-name: tada; + animation-name: tada; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes wobble { + 0% { + -webkit-transform: translateX(0%); + transform: translateX(0%); + } + + 15% { + -webkit-transform: translateX(-25%) rotate(-5deg); + transform: translateX(-25%) rotate(-5deg); + } + + 30% { + -webkit-transform: translateX(20%) rotate(3deg); + transform: translateX(20%) rotate(3deg); + } + + 45% { + -webkit-transform: translateX(-15%) rotate(-3deg); + transform: translateX(-15%) rotate(-3deg); + } + + 60% { + -webkit-transform: translateX(10%) rotate(2deg); + transform: translateX(10%) rotate(2deg); + } + + 75% { + -webkit-transform: translateX(-5%) rotate(-1deg); + transform: translateX(-5%) rotate(-1deg); + } + + 100% { + -webkit-transform: translateX(0%); + transform: translateX(0%); + } +} + +@keyframes wobble { + 0% { + -webkit-transform: translateX(0%); + -ms-transform: translateX(0%); + transform: translateX(0%); + } + + 15% { + -webkit-transform: translateX(-25%) rotate(-5deg); + -ms-transform: translateX(-25%) rotate(-5deg); + transform: translateX(-25%) rotate(-5deg); + } + + 30% { + -webkit-transform: translateX(20%) rotate(3deg); + -ms-transform: translateX(20%) rotate(3deg); + transform: translateX(20%) rotate(3deg); + } + + 45% { + -webkit-transform: translateX(-15%) rotate(-3deg); + -ms-transform: translateX(-15%) rotate(-3deg); + transform: translateX(-15%) rotate(-3deg); + } + + 60% { + -webkit-transform: translateX(10%) rotate(2deg); + -ms-transform: translateX(10%) rotate(2deg); + transform: translateX(10%) rotate(2deg); + } + + 75% { + -webkit-transform: translateX(-5%) rotate(-1deg); + -ms-transform: translateX(-5%) rotate(-1deg); + transform: translateX(-5%) rotate(-1deg); + } + + 100% { + -webkit-transform: translateX(0%); + -ms-transform: translateX(0%); + transform: translateX(0%); + } +} + +.wobble { + -webkit-animation-name: wobble; + animation-name: wobble; +} + +@-webkit-keyframes bounceIn { + 0% { + opacity: 0; + -webkit-transform: scale(.3); + transform: scale(.3); + } + + 50% { + opacity: 1; + -webkit-transform: scale(1.05); + transform: scale(1.05); + } + + 70% { + -webkit-transform: scale(.9); + transform: scale(.9); + } + + 100% { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@keyframes bounceIn { + 0% { + opacity: 0; + -webkit-transform: scale(.3); + -ms-transform: scale(.3); + transform: scale(.3); + } + + 50% { + opacity: 1; + -webkit-transform: scale(1.05); + -ms-transform: scale(1.05); + transform: scale(1.05); + } + + 70% { + -webkit-transform: scale(.9); + -ms-transform: scale(.9); + transform: scale(.9); + } + + 100% { + opacity: 1; + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + } +} + +.bounceIn { + -webkit-animation-name: bounceIn; + animation-name: bounceIn; +} + +@-webkit-keyframes bounceInDown { + 0% { + opacity: 0; + -webkit-transform: translateY(-2000px); + transform: translateY(-2000px); + } + + 60% { + opacity: 1; + -webkit-transform: translateY(30px); + transform: translateY(30px); + } + + 80% { + -webkit-transform: translateY(-10px); + transform: translateY(-10px); + } + + 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes bounceInDown { + 0% { + opacity: 0; + -webkit-transform: translateY(-2000px); + -ms-transform: translateY(-2000px); + transform: translateY(-2000px); + } + + 60% { + opacity: 1; + -webkit-transform: translateY(30px); + -ms-transform: translateY(30px); + transform: translateY(30px); + } + + 80% { + -webkit-transform: translateY(-10px); + -ms-transform: translateY(-10px); + transform: translateY(-10px); + } + + 100% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +.bounceInDown { + -webkit-animation-name: bounceInDown; + animation-name: bounceInDown; +} + +@-webkit-keyframes bounceInLeft { + 0% { + opacity: 0; + -webkit-transform: translateX(-2000px); + transform: translateX(-2000px); + } + + 60% { + opacity: 1; + -webkit-transform: translateX(30px); + transform: translateX(30px); + } + + 80% { + -webkit-transform: translateX(-10px); + transform: translateX(-10px); + } + + 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes bounceInLeft { + 0% { + opacity: 0; + -webkit-transform: translateX(-2000px); + -ms-transform: translateX(-2000px); + transform: translateX(-2000px); + } + + 60% { + opacity: 1; + -webkit-transform: translateX(30px); + -ms-transform: translateX(30px); + transform: translateX(30px); + } + + 80% { + -webkit-transform: translateX(-10px); + -ms-transform: translateX(-10px); + transform: translateX(-10px); + } + + 100% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } +} + +.bounceInLeft { + -webkit-animation-name: bounceInLeft; + animation-name: bounceInLeft; +} + +@-webkit-keyframes bounceInRight { + 0% { + opacity: 0; + -webkit-transform: translateX(2000px); + transform: translateX(2000px); + } + + 60% { + opacity: 1; + -webkit-transform: translateX(-30px); + transform: translateX(-30px); + } + + 80% { + -webkit-transform: translateX(10px); + transform: translateX(10px); + } + + 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes bounceInRight { + 0% { + opacity: 0; + -webkit-transform: translateX(2000px); + -ms-transform: translateX(2000px); + transform: translateX(2000px); + } + + 60% { + opacity: 1; + -webkit-transform: translateX(-30px); + -ms-transform: translateX(-30px); + transform: translateX(-30px); + } + + 80% { + -webkit-transform: translateX(10px); + -ms-transform: translateX(10px); + transform: translateX(10px); + } + + 100% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } +} + +.bounceInRight { + -webkit-animation-name: bounceInRight; + animation-name: bounceInRight; +} + +@-webkit-keyframes bounceInUp { + 0% { + opacity: 0; + -webkit-transform: translateY(2000px); + transform: translateY(2000px); + } + + 60% { + opacity: 1; + -webkit-transform: translateY(-30px); + transform: translateY(-30px); + } + + 80% { + -webkit-transform: translateY(10px); + transform: translateY(10px); + } + + 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes bounceInUp { + 0% { + opacity: 0; + -webkit-transform: translateY(2000px); + -ms-transform: translateY(2000px); + transform: translateY(2000px); + } + + 60% { + opacity: 1; + -webkit-transform: translateY(-30px); + -ms-transform: translateY(-30px); + transform: translateY(-30px); + } + + 80% { + -webkit-transform: translateY(10px); + -ms-transform: translateY(10px); + transform: translateY(10px); + } + + 100% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +.bounceInUp { + -webkit-animation-name: bounceInUp; + animation-name: bounceInUp; +} + +@-webkit-keyframes bounceOut { + 0% { + -webkit-transform: scale(1); + transform: scale(1); + } + + 25% { + -webkit-transform: scale(.95); + transform: scale(.95); + } + + 50% { + opacity: 1; + -webkit-transform: scale(1.1); + transform: scale(1.1); + } + + 100% { + opacity: 0; + -webkit-transform: scale(.3); + transform: scale(.3); + } +} + +@keyframes bounceOut { + 0% { + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + } + + 25% { + -webkit-transform: scale(.95); + -ms-transform: scale(.95); + transform: scale(.95); + } + + 50% { + opacity: 1; + -webkit-transform: scale(1.1); + -ms-transform: scale(1.1); + transform: scale(1.1); + } + + 100% { + opacity: 0; + -webkit-transform: scale(.3); + -ms-transform: scale(.3); + transform: scale(.3); + } +} + +.bounceOut { + -webkit-animation-name: bounceOut; + animation-name: bounceOut; +} + +@-webkit-keyframes bounceOutDown { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 20% { + opacity: 1; + -webkit-transform: translateY(-20px); + transform: translateY(-20px); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(2000px); + transform: translateY(2000px); + } +} + +@keyframes bounceOutDown { + 0% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 20% { + opacity: 1; + -webkit-transform: translateY(-20px); + -ms-transform: translateY(-20px); + transform: translateY(-20px); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(2000px); + -ms-transform: translateY(2000px); + transform: translateY(2000px); + } +} + +.bounceOutDown { + -webkit-animation-name: bounceOutDown; + animation-name: bounceOutDown; +} + +@-webkit-keyframes bounceOutLeft { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 20% { + opacity: 1; + -webkit-transform: translateX(20px); + transform: translateX(20px); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-2000px); + transform: translateX(-2000px); + } +} + +@keyframes bounceOutLeft { + 0% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 20% { + opacity: 1; + -webkit-transform: translateX(20px); + -ms-transform: translateX(20px); + transform: translateX(20px); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-2000px); + -ms-transform: translateX(-2000px); + transform: translateX(-2000px); + } +} + +.bounceOutLeft { + -webkit-animation-name: bounceOutLeft; + animation-name: bounceOutLeft; +} + +@-webkit-keyframes bounceOutRight { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 20% { + opacity: 1; + -webkit-transform: translateX(-20px); + transform: translateX(-20px); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(2000px); + transform: translateX(2000px); + } +} + +@keyframes bounceOutRight { + 0% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 20% { + opacity: 1; + -webkit-transform: translateX(-20px); + -ms-transform: translateX(-20px); + transform: translateX(-20px); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(2000px); + -ms-transform: translateX(2000px); + transform: translateX(2000px); + } +} + +.bounceOutRight { + -webkit-animation-name: bounceOutRight; + animation-name: bounceOutRight; +} + +@-webkit-keyframes bounceOutUp { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 20% { + opacity: 1; + -webkit-transform: translateY(20px); + transform: translateY(20px); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-2000px); + transform: translateY(-2000px); + } +} + +@keyframes bounceOutUp { + 0% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 20% { + opacity: 1; + -webkit-transform: translateY(20px); + -ms-transform: translateY(20px); + transform: translateY(20px); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-2000px); + -ms-transform: translateY(-2000px); + transform: translateY(-2000px); + } +} + +.bounceOutUp { + -webkit-animation-name: bounceOutUp; + animation-name: bounceOutUp; +} + +@-webkit-keyframes fadeIn { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes fadeIn { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +.fadeIn { + -webkit-animation-name: fadeIn; + animation-name: fadeIn; +} + +@-webkit-keyframes fadeInDown { + 0% { + opacity: 0; + -webkit-transform: translateY(-20px); + transform: translateY(-20px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes fadeInDown { + 0% { + opacity: 0; + -webkit-transform: translateY(-20px); + -ms-transform: translateY(-20px); + transform: translateY(-20px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +.fadeInDown { + -webkit-animation-name: fadeInDown; + animation-name: fadeInDown; +} + +@-webkit-keyframes fadeInDownBig { + 0% { + opacity: 0; + -webkit-transform: translateY(-2000px); + transform: translateY(-2000px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes fadeInDownBig { + 0% { + opacity: 0; + -webkit-transform: translateY(-2000px); + -ms-transform: translateY(-2000px); + transform: translateY(-2000px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +.fadeInDownBig { + -webkit-animation-name: fadeInDownBig; + animation-name: fadeInDownBig; +} + +@-webkit-keyframes fadeInLeft { + 0% { + opacity: 0; + -webkit-transform: translateX(-20px); + transform: translateX(-20px); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes fadeInLeft { + 0% { + opacity: 0; + -webkit-transform: translateX(-20px); + -ms-transform: translateX(-20px); + transform: translateX(-20px); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } +} + +.fadeInLeft { + -webkit-animation-name: fadeInLeft; + animation-name: fadeInLeft; +} + +@-webkit-keyframes fadeInLeftBig { + 0% { + opacity: 0; + -webkit-transform: translateX(-2000px); + transform: translateX(-2000px); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes fadeInLeftBig { + 0% { + opacity: 0; + -webkit-transform: translateX(-2000px); + -ms-transform: translateX(-2000px); + transform: translateX(-2000px); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } +} + +.fadeInLeftBig { + -webkit-animation-name: fadeInLeftBig; + animation-name: fadeInLeftBig; +} + +@-webkit-keyframes fadeInRight { + 0% { + opacity: 0; + -webkit-transform: translateX(20px); + transform: translateX(20px); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes fadeInRight { + 0% { + opacity: 0; + -webkit-transform: translateX(40px); + -ms-transform: translateX(40px); + transform: translateX(40px); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } +} + +.fadeInRight { + -webkit-animation-name: fadeInRight; + animation-name: fadeInRight; +} + +@-webkit-keyframes fadeInRightBig { + 0% { + opacity: 0; + -webkit-transform: translateX(2000px); + transform: translateX(2000px); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes fadeInRightBig { + 0% { + opacity: 0; + -webkit-transform: translateX(2000px); + -ms-transform: translateX(2000px); + transform: translateX(2000px); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } +} + +.fadeInRightBig { + -webkit-animation-name: fadeInRightBig; + animation-name: fadeInRightBig; +} + +@-webkit-keyframes fadeInUp { + 0% { + opacity: 0; + -webkit-transform: translateY(20px); + transform: translateY(20px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes fadeInUp { + 0% { + opacity: 0; + -webkit-transform: translateY(20px); + -ms-transform: translateY(20px); + transform: translateY(20px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +.fadeInUp { + -webkit-animation-name: fadeInUp; + animation-name: fadeInUp; +} + +@-webkit-keyframes fadeInUpBig { + 0% { + opacity: 0; + -webkit-transform: translateY(2000px); + transform: translateY(2000px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes fadeInUpBig { + 0% { + opacity: 0; + -webkit-transform: translateY(2000px); + -ms-transform: translateY(2000px); + transform: translateY(2000px); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +.fadeInUpBig { + -webkit-animation-name: fadeInUpBig; + animation-name: fadeInUpBig; +} + +@-webkit-keyframes fadeOut { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +@keyframes fadeOut { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +.fadeOut { + -webkit-animation-name: fadeOut; + animation-name: fadeOut; +} + +@-webkit-keyframes fadeOutDown { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(20px); + transform: translateY(20px); + } +} + +@keyframes fadeOutDown { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(20px); + -ms-transform: translateY(20px); + transform: translateY(20px); + } +} + +.fadeOutDown { + -webkit-animation-name: fadeOutDown; + animation-name: fadeOutDown; +} + +@-webkit-keyframes fadeOutDownBig { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(2000px); + transform: translateY(2000px); + } +} + +@keyframes fadeOutDownBig { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(2000px); + -ms-transform: translateY(2000px); + transform: translateY(2000px); + } +} + +.fadeOutDownBig { + -webkit-animation-name: fadeOutDownBig; + animation-name: fadeOutDownBig; +} + +@-webkit-keyframes fadeOutLeft { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-20px); + transform: translateX(-20px); + } +} + +@keyframes fadeOutLeft { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-20px); + -ms-transform: translateX(-20px); + transform: translateX(-20px); + } +} + +.fadeOutLeft { + -webkit-animation-name: fadeOutLeft; + animation-name: fadeOutLeft; +} + +@-webkit-keyframes fadeOutLeftBig { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-2000px); + transform: translateX(-2000px); + } +} + +@keyframes fadeOutLeftBig { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-2000px); + -ms-transform: translateX(-2000px); + transform: translateX(-2000px); + } +} + +.fadeOutLeftBig { + -webkit-animation-name: fadeOutLeftBig; + animation-name: fadeOutLeftBig; +} + +@-webkit-keyframes fadeOutRight { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(20px); + transform: translateX(20px); + } +} + +@keyframes fadeOutRight { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(20px); + -ms-transform: translateX(20px); + transform: translateX(20px); + } +} + +.fadeOutRight { + -webkit-animation-name: fadeOutRight; + animation-name: fadeOutRight; +} + +@-webkit-keyframes fadeOutRightBig { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(2000px); + transform: translateX(2000px); + } +} + +@keyframes fadeOutRightBig { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(2000px); + -ms-transform: translateX(2000px); + transform: translateX(2000px); + } +} + +.fadeOutRightBig { + -webkit-animation-name: fadeOutRightBig; + animation-name: fadeOutRightBig; +} + +@-webkit-keyframes fadeOutUp { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-20px); + transform: translateY(-20px); + } +} + +@keyframes fadeOutUp { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-20px); + -ms-transform: translateY(-20px); + transform: translateY(-20px); + } +} + +.fadeOutUp { + -webkit-animation-name: fadeOutUp; + animation-name: fadeOutUp; +} + +@-webkit-keyframes fadeOutUpBig { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-2000px); + transform: translateY(-2000px); + } +} + +@keyframes fadeOutUpBig { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-2000px); + -ms-transform: translateY(-2000px); + transform: translateY(-2000px); + } +} + +.fadeOutUpBig { + -webkit-animation-name: fadeOutUpBig; + animation-name: fadeOutUpBig; +} + +@-webkit-keyframes flip { + 0% { + -webkit-transform: perspective(400px) translateZ(0) rotateY(0) scale(1); + transform: perspective(400px) translateZ(0) rotateY(0) scale(1); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 40% { + -webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1); + transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 50% { + -webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1); + transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 80% { + -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95); + transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 100% { + -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1); + transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } +} + +@keyframes flip { + 0% { + -webkit-transform: perspective(400px) translateZ(0) rotateY(0) scale(1); + -ms-transform: perspective(400px) translateZ(0) rotateY(0) scale(1); + transform: perspective(400px) translateZ(0) rotateY(0) scale(1); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 40% { + -webkit-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1); + -ms-transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1); + transform: perspective(400px) translateZ(150px) rotateY(170deg) scale(1); + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 50% { + -webkit-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1); + -ms-transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1); + transform: perspective(400px) translateZ(150px) rotateY(190deg) scale(1); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 80% { + -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95); + -ms-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95); + transform: perspective(400px) translateZ(0) rotateY(360deg) scale(.95); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 100% { + -webkit-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1); + -ms-transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1); + transform: perspective(400px) translateZ(0) rotateY(360deg) scale(1); + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } +} + +.animated.flip { + -webkit-backface-visibility: visible; + -ms-backface-visibility: visible; + backface-visibility: visible; + -webkit-animation-name: flip; + animation-name: flip; +} + +@-webkit-keyframes flipInX { + 0% { + -webkit-transform: perspective(400px) rotateX(90deg); + transform: perspective(400px) rotateX(90deg); + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotateX(-10deg); + transform: perspective(400px) rotateX(-10deg); + } + + 70% { + -webkit-transform: perspective(400px) rotateX(10deg); + transform: perspective(400px) rotateX(10deg); + } + + 100% { + -webkit-transform: perspective(400px) rotateX(0deg); + transform: perspective(400px) rotateX(0deg); + opacity: 1; + } +} + +@keyframes flipInX { + 0% { + -webkit-transform: perspective(400px) rotateX(90deg); + -ms-transform: perspective(400px) rotateX(90deg); + transform: perspective(400px) rotateX(90deg); + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotateX(-10deg); + -ms-transform: perspective(400px) rotateX(-10deg); + transform: perspective(400px) rotateX(-10deg); + } + + 70% { + -webkit-transform: perspective(400px) rotateX(10deg); + -ms-transform: perspective(400px) rotateX(10deg); + transform: perspective(400px) rotateX(10deg); + } + + 100% { + -webkit-transform: perspective(400px) rotateX(0deg); + -ms-transform: perspective(400px) rotateX(0deg); + transform: perspective(400px) rotateX(0deg); + opacity: 1; + } +} + +.flipInX { + -webkit-backface-visibility: visible !important; + -ms-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipInX; + animation-name: flipInX; +} + +@-webkit-keyframes flipInY { + 0% { + -webkit-transform: perspective(400px) rotateY(90deg); + transform: perspective(400px) rotateY(90deg); + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotateY(-10deg); + transform: perspective(400px) rotateY(-10deg); + } + + 70% { + -webkit-transform: perspective(400px) rotateY(10deg); + transform: perspective(400px) rotateY(10deg); + } + + 100% { + -webkit-transform: perspective(400px) rotateY(0deg); + transform: perspective(400px) rotateY(0deg); + opacity: 1; + } +} + +@keyframes flipInY { + 0% { + -webkit-transform: perspective(400px) rotateY(90deg); + -ms-transform: perspective(400px) rotateY(90deg); + transform: perspective(400px) rotateY(90deg); + opacity: 0; + } + + 40% { + -webkit-transform: perspective(400px) rotateY(-10deg); + -ms-transform: perspective(400px) rotateY(-10deg); + transform: perspective(400px) rotateY(-10deg); + } + + 70% { + -webkit-transform: perspective(400px) rotateY(10deg); + -ms-transform: perspective(400px) rotateY(10deg); + transform: perspective(400px) rotateY(10deg); + } + + 100% { + -webkit-transform: perspective(400px) rotateY(0deg); + -ms-transform: perspective(400px) rotateY(0deg); + transform: perspective(400px) rotateY(0deg); + opacity: 1; + } +} + +.flipInY { + -webkit-backface-visibility: visible !important; + -ms-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipInY; + animation-name: flipInY; +} + +@-webkit-keyframes flipOutX { + 0% { + -webkit-transform: perspective(400px) rotateX(0deg); + transform: perspective(400px) rotateX(0deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(400px) rotateX(90deg); + transform: perspective(400px) rotateX(90deg); + opacity: 0; + } +} + +@keyframes flipOutX { + 0% { + -webkit-transform: perspective(400px) rotateX(0deg); + -ms-transform: perspective(400px) rotateX(0deg); + transform: perspective(400px) rotateX(0deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(400px) rotateX(90deg); + -ms-transform: perspective(400px) rotateX(90deg); + transform: perspective(400px) rotateX(90deg); + opacity: 0; + } +} + +.flipOutX { + -webkit-animation-name: flipOutX; + animation-name: flipOutX; + -webkit-backface-visibility: visible !important; + -ms-backface-visibility: visible !important; + backface-visibility: visible !important; +} + +@-webkit-keyframes flipOutY { + 0% { + -webkit-transform: perspective(400px) rotateY(0deg); + transform: perspective(400px) rotateY(0deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(400px) rotateY(90deg); + transform: perspective(400px) rotateY(90deg); + opacity: 0; + } +} + +@keyframes flipOutY { + 0% { + -webkit-transform: perspective(400px) rotateY(0deg); + -ms-transform: perspective(400px) rotateY(0deg); + transform: perspective(400px) rotateY(0deg); + opacity: 1; + } + + 100% { + -webkit-transform: perspective(400px) rotateY(90deg); + -ms-transform: perspective(400px) rotateY(90deg); + transform: perspective(400px) rotateY(90deg); + opacity: 0; + } +} + +.flipOutY { + -webkit-backface-visibility: visible !important; + -ms-backface-visibility: visible !important; + backface-visibility: visible !important; + -webkit-animation-name: flipOutY; + animation-name: flipOutY; +} + +@-webkit-keyframes lightSpeedIn { + 0% { + -webkit-transform: translateX(100%) skewX(-30deg); + transform: translateX(100%) skewX(-30deg); + opacity: 0; + } + + 60% { + -webkit-transform: translateX(-20%) skewX(30deg); + transform: translateX(-20%) skewX(30deg); + opacity: 1; + } + + 80% { + -webkit-transform: translateX(0%) skewX(-15deg); + transform: translateX(0%) skewX(-15deg); + opacity: 1; + } + + 100% { + -webkit-transform: translateX(0%) skewX(0deg); + transform: translateX(0%) skewX(0deg); + opacity: 1; + } +} + +@keyframes lightSpeedIn { + 0% { + -webkit-transform: translateX(100%) skewX(-30deg); + -ms-transform: translateX(100%) skewX(-30deg); + transform: translateX(100%) skewX(-30deg); + opacity: 0; + } + + 60% { + -webkit-transform: translateX(-20%) skewX(30deg); + -ms-transform: translateX(-20%) skewX(30deg); + transform: translateX(-20%) skewX(30deg); + opacity: 1; + } + + 80% { + -webkit-transform: translateX(0%) skewX(-15deg); + -ms-transform: translateX(0%) skewX(-15deg); + transform: translateX(0%) skewX(-15deg); + opacity: 1; + } + + 100% { + -webkit-transform: translateX(0%) skewX(0deg); + -ms-transform: translateX(0%) skewX(0deg); + transform: translateX(0%) skewX(0deg); + opacity: 1; + } +} + +.lightSpeedIn { + -webkit-animation-name: lightSpeedIn; + animation-name: lightSpeedIn; + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; +} + +@-webkit-keyframes lightSpeedOut { + 0% { + -webkit-transform: translateX(0%) skewX(0deg); + transform: translateX(0%) skewX(0deg); + opacity: 1; + } + + 100% { + -webkit-transform: translateX(100%) skewX(-30deg); + transform: translateX(100%) skewX(-30deg); + opacity: 0; + } +} + +@keyframes lightSpeedOut { + 0% { + -webkit-transform: translateX(0%) skewX(0deg); + -ms-transform: translateX(0%) skewX(0deg); + transform: translateX(0%) skewX(0deg); + opacity: 1; + } + + 100% { + -webkit-transform: translateX(100%) skewX(-30deg); + -ms-transform: translateX(100%) skewX(-30deg); + transform: translateX(100%) skewX(-30deg); + opacity: 0; + } +} + +.lightSpeedOut { + -webkit-animation-name: lightSpeedOut; + animation-name: lightSpeedOut; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; +} + +@-webkit-keyframes rotateIn { + 0% { + -webkit-transform-origin: center center; + transform-origin: center center; + -webkit-transform: rotate(-200deg); + transform: rotate(-200deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: center center; + transform-origin: center center; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +@keyframes rotateIn { + 0% { + -webkit-transform-origin: center center; + -ms-transform-origin: center center; + transform-origin: center center; + -webkit-transform: rotate(-200deg); + -ms-transform: rotate(-200deg); + transform: rotate(-200deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: center center; + -ms-transform-origin: center center; + transform-origin: center center; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +.rotateIn { + -webkit-animation-name: rotateIn; + animation-name: rotateIn; +} + +@-webkit-keyframes rotateInDownLeft { + 0% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +@keyframes rotateInDownLeft { + 0% { + -webkit-transform-origin: left bottom; + -ms-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: left bottom; + -ms-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +.rotateInDownLeft { + -webkit-animation-name: rotateInDownLeft; + animation-name: rotateInDownLeft; +} + +@-webkit-keyframes rotateInDownRight { + 0% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +@keyframes rotateInDownRight { + 0% { + -webkit-transform-origin: right bottom; + -ms-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: right bottom; + -ms-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +.rotateInDownRight { + -webkit-animation-name: rotateInDownRight; + animation-name: rotateInDownRight; +} + +@-webkit-keyframes rotateInUpLeft { + 0% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +@keyframes rotateInUpLeft { + 0% { + -webkit-transform-origin: left bottom; + -ms-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: left bottom; + -ms-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +.rotateInUpLeft { + -webkit-animation-name: rotateInUpLeft; + animation-name: rotateInUpLeft; +} + +@-webkit-keyframes rotateInUpRight { + 0% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +@keyframes rotateInUpRight { + 0% { + -webkit-transform-origin: right bottom; + -ms-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } + + 100% { + -webkit-transform-origin: right bottom; + -ms-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } +} + +.rotateInUpRight { + -webkit-animation-name: rotateInUpRight; + animation-name: rotateInUpRight; +} + +@-webkit-keyframes rotateOut { + 0% { + -webkit-transform-origin: center center; + transform-origin: center center; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: center center; + transform-origin: center center; + -webkit-transform: rotate(200deg); + transform: rotate(200deg); + opacity: 0; + } +} + +@keyframes rotateOut { + 0% { + -webkit-transform-origin: center center; + -ms-transform-origin: center center; + transform-origin: center center; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: center center; + -ms-transform-origin: center center; + transform-origin: center center; + -webkit-transform: rotate(200deg); + -ms-transform: rotate(200deg); + transform: rotate(200deg); + opacity: 0; + } +} + +.rotateOut { + -webkit-animation-name: rotateOut; + animation-name: rotateOut; +} + +@-webkit-keyframes rotateOutDownLeft { + 0% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } +} + +@keyframes rotateOutDownLeft { + 0% { + -webkit-transform-origin: left bottom; + -ms-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: left bottom; + -ms-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } +} + +.rotateOutDownLeft { + -webkit-animation-name: rotateOutDownLeft; + animation-name: rotateOutDownLeft; +} + +@-webkit-keyframes rotateOutDownRight { + 0% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } +} + +@keyframes rotateOutDownRight { + 0% { + -webkit-transform-origin: right bottom; + -ms-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: right bottom; + -ms-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } +} + +.rotateOutDownRight { + -webkit-animation-name: rotateOutDownRight; + animation-name: rotateOutDownRight; +} + +@-webkit-keyframes rotateOutUpLeft { + 0% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } +} + +@keyframes rotateOutUpLeft { + 0% { + -webkit-transform-origin: left bottom; + -ms-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: left bottom; + -ms-transform-origin: left bottom; + transform-origin: left bottom; + -webkit-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); + transform: rotate(-90deg); + opacity: 0; + } +} + +.rotateOutUpLeft { + -webkit-animation-name: rotateOutUpLeft; + animation-name: rotateOutUpLeft; +} + +@-webkit-keyframes rotateOutUpRight { + 0% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } +} + +@keyframes rotateOutUpRight { + 0% { + -webkit-transform-origin: right bottom; + -ms-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + opacity: 1; + } + + 100% { + -webkit-transform-origin: right bottom; + -ms-transform-origin: right bottom; + transform-origin: right bottom; + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); + opacity: 0; + } +} + +.rotateOutUpRight { + -webkit-animation-name: rotateOutUpRight; + animation-name: rotateOutUpRight; +} + +@-webkit-keyframes slideInDown { + 0% { + opacity: 0; + -webkit-transform: translateY(-2000px); + transform: translateY(-2000px); + } + + 100% { + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes slideInDown { + 0% { + opacity: 0; + -webkit-transform: translateY(-2000px); + -ms-transform: translateY(-2000px); + transform: translateY(-2000px); + } + + 100% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } +} + +.slideInDown { + -webkit-animation-name: slideInDown; + animation-name: slideInDown; +} + +@-webkit-keyframes slideInLeft { + 0% { + opacity: 0; + -webkit-transform: translateX(-2000px); + transform: translateX(-2000px); + } + + 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes slideInLeft { + 0% { + opacity: 0; + -webkit-transform: translateX(-2000px); + -ms-transform: translateX(-2000px); + transform: translateX(-2000px); + } + + 100% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } +} + +.slideInLeft { + -webkit-animation-name: slideInLeft; + animation-name: slideInLeft; +} + +@-webkit-keyframes slideInRight { + 0% { + opacity: 0; + -webkit-transform: translateX(2000px); + transform: translateX(2000px); + } + + 100% { + -webkit-transform: translateX(0); + transform: translateX(0); + } +} + +@keyframes slideInRight { + 0% { + opacity: 0; + -webkit-transform: translateX(2000px); + -ms-transform: translateX(2000px); + transform: translateX(2000px); + } + + 100% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } +} + +.slideInRight { + -webkit-animation-name: slideInRight; + animation-name: slideInRight; +} + +@-webkit-keyframes slideOutLeft { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-2000px); + transform: translateX(-2000px); + } +} + +@keyframes slideOutLeft { + 0% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(-2000px); + -ms-transform: translateX(-2000px); + transform: translateX(-2000px); + } +} + +.slideOutLeft { + -webkit-animation-name: slideOutLeft; + animation-name: slideOutLeft; +} + +@-webkit-keyframes slideOutRight { + 0% { + -webkit-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(2000px); + transform: translateX(2000px); + } +} + +@keyframes slideOutRight { + 0% { + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(2000px); + -ms-transform: translateX(2000px); + transform: translateX(2000px); + } +} + +.slideOutRight { + -webkit-animation-name: slideOutRight; + animation-name: slideOutRight; +} + +@-webkit-keyframes slideOutUp { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-2000px); + transform: translateY(-2000px); + } +} + +@keyframes slideOutUp { + 0% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(-2000px); + -ms-transform: translateY(-2000px); + transform: translateY(-2000px); + } +} + +.slideOutUp { + -webkit-animation-name: slideOutUp; + animation-name: slideOutUp; +} + +@-webkit-keyframes slideOutDown { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(2000px); + transform: translateY(2000px); + } +} + +@keyframes slideOutDown { + 0% { + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + + 100% { + opacity: 0; + -webkit-transform: translateY(2000px); + -ms-transform: translateY(2000px); + transform: translateY(2000px); + } +} + +.slideOutDown { + -webkit-animation-name: slideOutDown; + animation-name: slideOutDown; +} + +@-webkit-keyframes hinge { + 0% { + -webkit-transform: rotate(0); + transform: rotate(0); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 20%, 60% { + -webkit-transform: rotate(80deg); + transform: rotate(80deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 40% { + -webkit-transform: rotate(60deg); + transform: rotate(60deg); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 80% { + -webkit-transform: rotate(60deg) translateY(0); + transform: rotate(60deg) translateY(0); + -webkit-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + opacity: 1; + } + + 100% { + -webkit-transform: translateY(700px); + transform: translateY(700px); + opacity: 0; + } +} + +@keyframes hinge { + 0% { + -webkit-transform: rotate(0); + -ms-transform: rotate(0); + transform: rotate(0); + -webkit-transform-origin: top left; + -ms-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 20%, 60% { + -webkit-transform: rotate(80deg); + -ms-transform: rotate(80deg); + transform: rotate(80deg); + -webkit-transform-origin: top left; + -ms-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 40% { + -webkit-transform: rotate(60deg); + -ms-transform: rotate(60deg); + transform: rotate(60deg); + -webkit-transform-origin: top left; + -ms-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + } + + 80% { + -webkit-transform: rotate(60deg) translateY(0); + -ms-transform: rotate(60deg) translateY(0); + transform: rotate(60deg) translateY(0); + -webkit-transform-origin: top left; + -ms-transform-origin: top left; + transform-origin: top left; + -webkit-animation-timing-function: ease-in-out; + animation-timing-function: ease-in-out; + opacity: 1; + } + + 100% { + -webkit-transform: translateY(700px); + -ms-transform: translateY(700px); + transform: translateY(700px); + opacity: 0; + } +} + +.hinge { + -webkit-animation-name: hinge; + animation-name: hinge; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes rollIn { + 0% { + opacity: 0; + -webkit-transform: translateX(-100%) rotate(-120deg); + transform: translateX(-100%) rotate(-120deg); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0px) rotate(0deg); + transform: translateX(0px) rotate(0deg); + } +} + +@keyframes rollIn { + 0% { + opacity: 0; + -webkit-transform: translateX(-100%) rotate(-120deg); + -ms-transform: translateX(-100%) rotate(-120deg); + transform: translateX(-100%) rotate(-120deg); + } + + 100% { + opacity: 1; + -webkit-transform: translateX(0px) rotate(0deg); + -ms-transform: translateX(0px) rotate(0deg); + transform: translateX(0px) rotate(0deg); + } +} + +.rollIn { + -webkit-animation-name: rollIn; + animation-name: rollIn; +} + +/* originally authored by Nick Pettit - https://github.com/nickpettit/glide */ + +@-webkit-keyframes rollOut { + 0% { + opacity: 1; + -webkit-transform: translateX(0px) rotate(0deg); + transform: translateX(0px) rotate(0deg); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(100%) rotate(120deg); + transform: translateX(100%) rotate(120deg); + } +} + +@keyframes rollOut { + 0% { + opacity: 1; + -webkit-transform: translateX(0px) rotate(0deg); + -ms-transform: translateX(0px) rotate(0deg); + transform: translateX(0px) rotate(0deg); + } + + 100% { + opacity: 0; + -webkit-transform: translateX(100%) rotate(120deg); + -ms-transform: translateX(100%) rotate(120deg); + transform: translateX(100%) rotate(120deg); + } +} + +.rollOut { + -webkit-animation-name: rollOut; + animation-name: rollOut; +} \ No newline at end of file diff --git a/static/css/bootstrap.min.css b/static/css/bootstrap.min.css new file mode 100644 index 000000000000..4af8905e5b8a --- /dev/null +++ b/static/css/bootstrap.min.css @@ -0,0 +1,5 @@ +/*! + * Bootstrap v3.3.0 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:before,:after{color:#000!important;text-shadow:none!important;background:transparent!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:before,:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:400;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=radio],input[type=checkbox]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=radio]:focus,input[type=checkbox]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{line-height:34px;line-height:1.42857143 \0}input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px;line-height:1.5 \0}input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px;line-height:1.33 \0}_:-ms-fullscreen,:root input[type=date],_:-ms-fullscreen,:root input[type=time],_:-ms-fullscreen,:root input[type=datetime-local],_:-ms-fullscreen,:root input[type=month]{line-height:1.42857143}_:-ms-fullscreen.input-sm,:root input[type=date].input-sm,_:-ms-fullscreen.input-sm,:root input[type=time].input-sm,_:-ms-fullscreen.input-sm,:root input[type=datetime-local].input-sm,_:-ms-fullscreen.input-sm,:root input[type=month].input-sm{line-height:1.5}_:-ms-fullscreen.input-lg,:root input[type=date].input-lg,_:-ms-fullscreen.input-lg,:root input[type=time].input-lg,_:-ms-fullscreen.input-lg,:root input[type=datetime-local].input-lg,_:-ms-fullscreen.input-lg,:root input[type=month].input-lg{line-height:1.33}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.radio input[type=radio],.radio-inline input[type=radio],.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox]{position:absolute;margin-top:4px \9;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type=radio][disabled],input[type=checkbox][disabled],input[type=radio].disabled,input[type=checkbox].disabled,fieldset[disabled] input[type=radio],fieldset[disabled] input[type=checkbox]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm,.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm,select.form-group-sm .form-control{height:30px;line-height:30px}textarea.input-sm,textarea.form-group-sm .form-control,select[multiple].input-sm,select[multiple].form-group-sm .form-control{height:auto}.input-lg,.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg,select.form-group-lg .form-control{height:46px;line-height:46px}textarea.input-lg,textarea.form-group-lg .form-control,select[multiple].input-lg,select[multiple].form-group-lg .form-control{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type=radio],.form-inline .checkbox input[type=checkbox]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.3px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default.focus,.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary.focus,.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#3071a9;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success.focus,.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info.focus,.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning.focus,.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger.focus,.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#428bca;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none;visibility:hidden}.collapse.in{display:block;visibility:visible}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#428bca;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px solid}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=radio],[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=radio],.input-group-addon input[type=checkbox]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none;visibility:hidden}.tab-content>.active{display:block;visibility:visible}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important;visibility:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type=radio],.navbar-form .checkbox input[type=checkbox]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#fff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#428bca;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#2a6496;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;cursor:default;background-color:#428bca;border-color:#428bca}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:hover,.label-default[href]:focus{background-color:#5e5e5e}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px 15px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding:48px 0}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-right:auto;margin-left:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar,.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);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{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)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{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)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{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)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{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)}.media{margin-top:15px}.media:first-child{margin-top:0}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{color:#555;text-decoration:none;background-color:#f5f5f5}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-right:15px;padding-left:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#428bca}.panel-primary>.panel-heading .badge{color:#428bca;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-size:12px;line-height:1.4;visibility:visible;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-size:14px;font-weight:400;line-height:1.42857143;text-align:left;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000;perspective:1000}.carousel-inner>.item.next,.carousel-inner>.item.active.right{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{display:table;content:" "}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none!important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} \ No newline at end of file diff --git a/static/css/colorbox.css b/static/css/colorbox.css new file mode 100644 index 000000000000..0a6710404034 --- /dev/null +++ b/static/css/colorbox.css @@ -0,0 +1,50 @@ +/* + Colorbox Core Style: + The following CSS is consistent between example themes and should not be altered. +*/ +#colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden;} +#cboxWrapper {max-width:none;} +#cboxOverlay{position:fixed; width:100%; height:100%;} +#cboxMiddleLeft, #cboxBottomLeft{clear:left;} +#cboxContent{position:relative;} +#cboxLoadedContent{overflow:auto; -webkit-overflow-scrolling: touch;} +#cboxTitle{margin:0;} +#cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%; height:100%;} +#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;} +.cboxPhoto{float:left; margin:auto; border:0; display:block; max-width:none; -ms-interpolation-mode:bicubic;} +.cboxIframe{width:100%; height:100%; display:block; border:0; padding:0; margin:0;} +#colorbox, #cboxContent, #cboxLoadedContent{box-sizing:content-box; -moz-box-sizing:content-box; -webkit-box-sizing:content-box;} + +/* + User Style: + Change the following styles to modify the appearance of Colorbox. They are + ordered & tabbed in a way that represents the nesting of the generated HTML. +*/ +#cboxOverlay{background:#fff; opacity: 0.9; filter: alpha(opacity = 90);} +#colorbox{outline:0;} + #cboxContent{margin-top:32px; overflow:visible; background:#000;} + .cboxIframe{background:#fff;} + #cboxError{padding:50px; border:1px solid #ccc;} + #cboxLoadedContent{background:#000; padding:1px;} + #cboxLoadingGraphic{background:url(images/loading.gif) no-repeat center center;} + #cboxLoadingOverlay{background:#000;} + #cboxTitle{position:absolute; top:-22px; left:0; color:#000;} + #cboxCurrent{position:absolute; top:-22px; right:205px; text-indent:-9999px;} + + /* these elements are buttons, and may need to have additional styles reset to avoid unwanted base styles */ + #cboxPrevious, #cboxNext, #cboxSlideshow, #cboxClose {border:0; padding:0; margin:0; overflow:visible; text-indent:-9999px; width:20px; height:20px; position:absolute; top:-20px; background:url(images/controls.png) no-repeat 0 0;} + + /* avoid outlines on :active (mouseclick), but preserve outlines on :focus (tabbed navigating) */ + #cboxPrevious:active, #cboxNext:active, #cboxSlideshow:active, #cboxClose:active {outline:0;} + + #cboxPrevious{background-position:0px 0px; right:44px;} + #cboxPrevious:hover{background-position:0px -25px;} + #cboxNext{background-position:-25px 0px; right:22px;} + #cboxNext:hover{background-position:-25px -25px;} + #cboxClose{background-position:-50px 0px; right:0;} + #cboxClose:hover{background-position:-50px -25px;} + .cboxSlideshow_on #cboxPrevious, .cboxSlideshow_off #cboxPrevious{right:66px;} + .cboxSlideshow_on #cboxSlideshow{background-position:-75px -25px; right:44px;} + .cboxSlideshow_on #cboxSlideshow:hover{background-position:-100px -25px;} + .cboxSlideshow_off #cboxSlideshow{background-position:-100px 0px; right:44px;} + .cboxSlideshow_off #cboxSlideshow:hover{background-position:-75px -25px;} diff --git a/static/css/images/controls.png b/static/css/images/controls.png new file mode 100644 index 000000000000..36f5269929f7 Binary files /dev/null and b/static/css/images/controls.png differ diff --git a/static/css/images/loading.gif b/static/css/images/loading.gif new file mode 100644 index 000000000000..a32df5c0881b Binary files /dev/null and b/static/css/images/loading.gif differ diff --git a/static/css/magnific/magnific-popup.css b/static/css/magnific/magnific-popup.css new file mode 100644 index 000000000000..a530c65ae193 --- /dev/null +++ b/static/css/magnific/magnific-popup.css @@ -0,0 +1,374 @@ +/* Magnific Popup CSS */ +.mfp-bg { + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1042; + overflow: hidden; + position: fixed; + background: #0b0b0b; + opacity: 0.8; + filter: alpha(opacity=80); } + +.mfp-wrap { + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1043; + position: fixed; + outline: none !important; + -webkit-backface-visibility: hidden; } + +.mfp-container { + text-align: center; + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + padding: 0 8px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + +.mfp-container:before { + content: ''; + display: inline-block; + height: 100%; + vertical-align: middle; } + +.mfp-align-top .mfp-container:before { + display: none; } + +.mfp-content { + position: relative; + display: inline-block; + vertical-align: middle; + margin: 0 auto; + text-align: left; + z-index: 1045; } + +.mfp-inline-holder .mfp-content, .mfp-ajax-holder .mfp-content { + width: 100%; + cursor: auto; } + +.mfp-ajax-cur { + cursor: progress; } + +.mfp-zoom-out-cur, .mfp-zoom-out-cur .mfp-image-holder .mfp-close { + cursor: -moz-zoom-out; + cursor: -webkit-zoom-out; + cursor: zoom-out; } + +.mfp-zoom { + cursor: pointer; + cursor: -webkit-zoom-in; + cursor: -moz-zoom-in; + cursor: zoom-in; } + +.mfp-auto-cursor .mfp-content { + cursor: auto; } + +.mfp-close, .mfp-arrow, .mfp-preloader, .mfp-counter { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; } + +.mfp-loading.mfp-figure { + display: none; } + +.mfp-hide { + display: none !important; } + +.mfp-preloader { + color: #CCC; + position: absolute; + top: 50%; + width: auto; + text-align: center; + margin-top: -0.8em; + left: 8px; + right: 8px; + z-index: 1044; } + .mfp-preloader a { + color: #CCC; } + .mfp-preloader a:hover { + color: #FFF; } + +.mfp-s-ready .mfp-preloader { + display: none; } + +.mfp-s-error .mfp-content { + display: none; } + +button.mfp-close, button.mfp-arrow { + overflow: visible; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; + display: block; + outline: none; + padding: 0; + z-index: 1046; + -webkit-box-shadow: none; + box-shadow: none; } +button::-moz-focus-inner { + padding: 0; + border: 0; } + +.mfp-close { + width: 44px; + height: 44px; + line-height: 44px; + position: absolute; + right: 0; + top: 0; + text-decoration: none; + text-align: center; + opacity: 0.65; + filter: alpha(opacity=65); + padding: 0 0 18px 10px; + color: #FFF; + font-style: normal; + font-size: 28px; + font-family: Arial, Baskerville, monospace; } + .mfp-close:hover, .mfp-close:focus { + opacity: 1; + filter: alpha(opacity=100); } + .mfp-close:active { + top: 1px; } + +.mfp-close-btn-in .mfp-close { + color: #333; } + +.mfp-image-holder .mfp-close, .mfp-iframe-holder .mfp-close { + color: #FFF; + right: -6px; + text-align: right; + padding-right: 6px; + width: 100%; } + +.mfp-counter { + position: absolute; + top: 0; + right: 0; + color: #CCC; + font-size: 12px; + line-height: 18px; + white-space: nowrap; } + +.mfp-arrow { + position: absolute; + opacity: 0.65; + filter: alpha(opacity=65); + margin: 0; + top: 50%; + margin-top: -55px; + padding: 0; + width: 90px; + height: 110px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } + .mfp-arrow:active { + margin-top: -54px; } + .mfp-arrow:hover, .mfp-arrow:focus { + opacity: 1; + filter: alpha(opacity=100); } + .mfp-arrow:before, .mfp-arrow:after, .mfp-arrow .mfp-b, .mfp-arrow .mfp-a { + content: ''; + display: block; + width: 0; + height: 0; + position: absolute; + left: 0; + top: 0; + margin-top: 35px; + margin-left: 35px; + border: medium inset transparent; } + .mfp-arrow:after, .mfp-arrow .mfp-a { + border-top-width: 13px; + border-bottom-width: 13px; + top: 8px; } + .mfp-arrow:before, .mfp-arrow .mfp-b { + border-top-width: 21px; + border-bottom-width: 21px; + opacity: 0.7; } + +.mfp-arrow-left { + left: 0; } + .mfp-arrow-left:after, .mfp-arrow-left .mfp-a { + border-right: 17px solid #FFF; + margin-left: 31px; } + .mfp-arrow-left:before, .mfp-arrow-left .mfp-b { + margin-left: 25px; + border-right: 27px solid #3F3F3F; } + +.mfp-arrow-right { + right: 0; } + .mfp-arrow-right:after, .mfp-arrow-right .mfp-a { + border-left: 17px solid #FFF; + margin-left: 39px; } + .mfp-arrow-right:before, .mfp-arrow-right .mfp-b { + border-left: 27px solid #3F3F3F; } + +.mfp-iframe-holder { + padding-top: 40px; + padding-bottom: 40px; } + .mfp-iframe-holder .mfp-content { + line-height: 0; + width: 100%; + max-width: 900px; } + .mfp-iframe-holder .mfp-close { + top: -40px; } + +.mfp-iframe-scaler { + width: 100%; + height: 0; + overflow: hidden; + padding-top: 56.25%; } + .mfp-iframe-scaler iframe { + position: absolute; + display: block; + top: 0; + left: 0; + width: 100%; + height: 100%; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.6); + background: #000; } + +/* Main image in popup */ +img.mfp-img { + width: auto; + max-width: 100%; + height: auto; + display: block; + line-height: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 40px 0 40px; + margin: 0 auto; } + +/* The shadow behind the image */ +.mfp-figure { + line-height: 0; } + .mfp-figure:after { + content: ''; + position: absolute; + left: 0; + top: 40px; + bottom: 40px; + display: block; + right: 0; + width: auto; + height: auto; + z-index: -1; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.6); + background: #444; } + .mfp-figure small { + color: #BDBDBD; + display: block; + font-size: 12px; + line-height: 14px; } + .mfp-figure figure { + margin: 0; } + +.mfp-bottom-bar { + margin-top: -36px; + position: absolute; + top: 100%; + left: 0; + width: 100%; + cursor: auto; } + +.mfp-title { + text-align: left; + line-height: 18px; + color: #F3F3F3; + word-wrap: break-word; + padding-right: 36px; } + +.mfp-image-holder .mfp-content { + max-width: 100%; } + +.mfp-gallery .mfp-image-holder .mfp-figure { + cursor: pointer; } + +@media screen and (max-width: 800px) and (orientation: landscape), screen and (max-height: 300px) { + /** + * Remove all paddings around the image on small screen + */ + .mfp-img-mobile .mfp-image-holder { + padding-left: 0; + padding-right: 0; } + .mfp-img-mobile img.mfp-img { + padding: 0; } + .mfp-img-mobile .mfp-figure:after { + top: 0; + bottom: 0; } + .mfp-img-mobile .mfp-figure small { + display: inline; + margin-left: 5px; } + .mfp-img-mobile .mfp-bottom-bar { + background: rgba(0, 0, 0, 0.6); + bottom: 0; + margin: 0; + top: auto; + padding: 3px 5px; + position: fixed; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + .mfp-img-mobile .mfp-bottom-bar:empty { + padding: 0; } + .mfp-img-mobile .mfp-counter { + right: 5px; + top: 3px; } + .mfp-img-mobile .mfp-close { + top: 0; + right: 0; + width: 35px; + height: 35px; + line-height: 35px; + background: rgba(0, 0, 0, 0.6); + position: fixed; + text-align: center; + padding: 0; } + } + +@media all and (max-width: 900px) { + .mfp-arrow { + -webkit-transform: scale(0.75); + transform: scale(0.75); } + + .mfp-arrow-left { + -webkit-transform-origin: 0; + transform-origin: 0; } + + .mfp-arrow-right { + -webkit-transform-origin: 100%; + transform-origin: 100%; } + + .mfp-container { + padding-left: 6px; + padding-right: 6px; } + } + +.mfp-ie7 .mfp-img { + padding: 0; } +.mfp-ie7 .mfp-bottom-bar { + width: 600px; + left: 50%; + margin-left: -300px; + margin-top: 5px; + padding-bottom: 5px; } +.mfp-ie7 .mfp-container { + padding: 0; } +.mfp-ie7 .mfp-content { + padding-top: 44px; } +.mfp-ie7 .mfp-close { + top: 0; + right: 0; + padding-top: 0; } diff --git a/static/css/patterns/congruent_pentagon.png b/static/css/patterns/congruent_pentagon.png new file mode 100644 index 000000000000..c71266032802 Binary files /dev/null and b/static/css/patterns/congruent_pentagon.png differ diff --git a/static/css/patterns/header-profile-skin-1.png b/static/css/patterns/header-profile-skin-1.png new file mode 100644 index 000000000000..41c5c089bbf7 Binary files /dev/null and b/static/css/patterns/header-profile-skin-1.png differ diff --git a/static/css/patterns/header-profile-skin-2.png b/static/css/patterns/header-profile-skin-2.png new file mode 100644 index 000000000000..df46d46e5869 Binary files /dev/null and b/static/css/patterns/header-profile-skin-2.png differ diff --git a/static/css/patterns/header-profile-skin-3.png b/static/css/patterns/header-profile-skin-3.png new file mode 100644 index 000000000000..7a80132da83d Binary files /dev/null and b/static/css/patterns/header-profile-skin-3.png differ diff --git a/static/css/patterns/header-profile.png b/static/css/patterns/header-profile.png new file mode 100644 index 000000000000..7dea7f2c7629 Binary files /dev/null and b/static/css/patterns/header-profile.png differ diff --git a/static/css/patterns/otis_redding.png b/static/css/patterns/otis_redding.png new file mode 100644 index 000000000000..7fa3533a0098 Binary files /dev/null and b/static/css/patterns/otis_redding.png differ diff --git a/static/css/patterns/shattered.png b/static/css/patterns/shattered.png new file mode 100644 index 000000000000..90ed42b85b7b Binary files /dev/null and b/static/css/patterns/shattered.png differ diff --git a/static/css/patterns/triangular.png b/static/css/patterns/triangular.png new file mode 100644 index 000000000000..7f41795c8878 Binary files /dev/null and b/static/css/patterns/triangular.png differ diff --git a/static/css/plugins/dropzone/basic.css b/static/css/plugins/dropzone/basic.css new file mode 100644 index 000000000000..83084dbe1795 --- /dev/null +++ b/static/css/plugins/dropzone/basic.css @@ -0,0 +1,155 @@ +/* The MIT License */ +.dropzone, +.dropzone *, +.dropzone-previews, +.dropzone-previews * { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.dropzone { + position: relative; + border: 1px solid rgba(0,0,0,0.08); + background: rgba(0,0,0,0.02); + padding: 1em; +} +.dropzone.dz-clickable { + cursor: pointer; +} +.dropzone.dz-clickable .dz-message, +.dropzone.dz-clickable .dz-message span { + cursor: pointer; +} +.dropzone.dz-clickable * { + cursor: default; +} +.dropzone .dz-message { + opacity: 1; + -ms-filter: none; + filter: none; +} +.dropzone.dz-drag-hover { + border-color: rgba(0,0,0,0.15); + background: rgba(0,0,0,0.04); +} +.dropzone.dz-started .dz-message { + display: none; +} +.dropzone .dz-preview, +.dropzone-previews .dz-preview { + background: rgba(255,255,255,0.8); + position: relative; + display: inline-block; + margin: 17px; + vertical-align: top; + border: 1px solid #acacac; + padding: 6px 6px 6px 6px; +} +.dropzone .dz-preview.dz-file-preview [data-dz-thumbnail], +.dropzone-previews .dz-preview.dz-file-preview [data-dz-thumbnail] { + display: none; +} +.dropzone .dz-preview .dz-details, +.dropzone-previews .dz-preview .dz-details { + width: 100px; + height: 100px; + position: relative; + background: #ebebeb; + padding: 5px; + margin-bottom: 22px; +} +.dropzone .dz-preview .dz-details .dz-filename, +.dropzone-previews .dz-preview .dz-details .dz-filename { + overflow: hidden; + height: 100%; +} +.dropzone .dz-preview .dz-details img, +.dropzone-previews .dz-preview .dz-details img { + position: absolute; + top: 0; + left: 0; + width: 100px; + height: 100px; +} +.dropzone .dz-preview .dz-details .dz-size, +.dropzone-previews .dz-preview .dz-details .dz-size { + position: absolute; + bottom: -28px; + left: 3px; + height: 28px; + line-height: 28px; +} +.dropzone .dz-preview.dz-error .dz-error-mark, +.dropzone-previews .dz-preview.dz-error .dz-error-mark { + display: block; +} +.dropzone .dz-preview.dz-success .dz-success-mark, +.dropzone-previews .dz-preview.dz-success .dz-success-mark { + display: block; +} +.dropzone .dz-preview:hover .dz-details img, +.dropzone-previews .dz-preview:hover .dz-details img { + display: none; +} +.dropzone .dz-preview .dz-success-mark, +.dropzone-previews .dz-preview .dz-success-mark, +.dropzone .dz-preview .dz-error-mark, +.dropzone-previews .dz-preview .dz-error-mark { + display: none; + position: absolute; + width: 40px; + height: 40px; + font-size: 30px; + text-align: center; + right: -10px; + top: -10px; +} +.dropzone .dz-preview .dz-success-mark, +.dropzone-previews .dz-preview .dz-success-mark { + color: #8cc657; +} +.dropzone .dz-preview .dz-error-mark, +.dropzone-previews .dz-preview .dz-error-mark { + color: #ee162d; +} +.dropzone .dz-preview .dz-progress, +.dropzone-previews .dz-preview .dz-progress { + position: absolute; + top: 100px; + left: 6px; + right: 6px; + height: 6px; + background: #d7d7d7; + display: none; +} +.dropzone .dz-preview .dz-progress .dz-upload, +.dropzone-previews .dz-preview .dz-progress .dz-upload { + display: block; + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 0%; + background-color: #8cc657; +} +.dropzone .dz-preview.dz-processing .dz-progress, +.dropzone-previews .dz-preview.dz-processing .dz-progress { + display: block; +} +.dropzone .dz-preview .dz-error-message, +.dropzone-previews .dz-preview .dz-error-message { + display: none; + position: absolute; + top: -5px; + left: -20px; + background: rgba(245,245,245,0.8); + padding: 8px 10px; + color: #800; + min-width: 140px; + max-width: 500px; + z-index: 500; +} +.dropzone .dz-preview:hover.dz-error .dz-error-message, +.dropzone-previews .dz-preview:hover.dz-error .dz-error-message { + display: block; +} diff --git a/static/css/plugins/dropzone/dropzone.css b/static/css/plugins/dropzone/dropzone.css new file mode 100644 index 000000000000..fc18729c5a4b --- /dev/null +++ b/static/css/plugins/dropzone/dropzone.css @@ -0,0 +1,410 @@ +/* The MIT License */ +.dropzone, +.dropzone *, +.dropzone-previews, +.dropzone-previews * { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.dropzone { + position: relative; + border: 1px solid rgba(0,0,0,0.08); + background: rgba(0,0,0,0.02); + padding: 1em; +} +.dropzone.dz-clickable { + cursor: pointer; +} +.dropzone.dz-clickable .dz-message, +.dropzone.dz-clickable .dz-message span { + cursor: pointer; +} +.dropzone.dz-clickable * { + cursor: default; +} +.dropzone .dz-message { + opacity: 1; + -ms-filter: none; + filter: none; +} +.dropzone.dz-drag-hover { + border-color: rgba(0,0,0,0.15); + background: rgba(0,0,0,0.04); +} +.dropzone.dz-started .dz-message { + display: none; +} +.dropzone .dz-preview, +.dropzone-previews .dz-preview { + background: rgba(255,255,255,0.8); + position: relative; + display: inline-block; + margin: 17px; + vertical-align: top; + border: 1px solid #acacac; + padding: 6px 6px 6px 6px; +} +.dropzone .dz-preview.dz-file-preview [data-dz-thumbnail], +.dropzone-previews .dz-preview.dz-file-preview [data-dz-thumbnail] { + display: none; +} +.dropzone .dz-preview .dz-details, +.dropzone-previews .dz-preview .dz-details { + width: 100px; + height: 100px; + position: relative; + background: #ebebeb; + padding: 5px; + margin-bottom: 22px; +} +.dropzone .dz-preview .dz-details .dz-filename, +.dropzone-previews .dz-preview .dz-details .dz-filename { + overflow: hidden; + height: 100%; +} +.dropzone .dz-preview .dz-details img, +.dropzone-previews .dz-preview .dz-details img { + position: absolute; + top: 0; + left: 0; + width: 100px; + height: 100px; +} +.dropzone .dz-preview .dz-details .dz-size, +.dropzone-previews .dz-preview .dz-details .dz-size { + position: absolute; + bottom: -28px; + left: 3px; + height: 28px; + line-height: 28px; +} +.dropzone .dz-preview.dz-error .dz-error-mark, +.dropzone-previews .dz-preview.dz-error .dz-error-mark { + display: block; +} +.dropzone .dz-preview.dz-success .dz-success-mark, +.dropzone-previews .dz-preview.dz-success .dz-success-mark { + display: block; +} +.dropzone .dz-preview:hover .dz-details img, +.dropzone-previews .dz-preview:hover .dz-details img { + display: none; +} +.dropzone .dz-preview .dz-success-mark, +.dropzone-previews .dz-preview .dz-success-mark, +.dropzone .dz-preview .dz-error-mark, +.dropzone-previews .dz-preview .dz-error-mark { + display: none; + position: absolute; + width: 40px; + height: 40px; + font-size: 30px; + text-align: center; + right: -10px; + top: -10px; +} +.dropzone .dz-preview .dz-success-mark, +.dropzone-previews .dz-preview .dz-success-mark { + color: #8cc657; +} +.dropzone .dz-preview .dz-error-mark, +.dropzone-previews .dz-preview .dz-error-mark { + color: #ee162d; +} +.dropzone .dz-preview .dz-progress, +.dropzone-previews .dz-preview .dz-progress { + position: absolute; + top: 100px; + left: 6px; + right: 6px; + height: 6px; + background: #d7d7d7; + display: none; +} +.dropzone .dz-preview .dz-progress .dz-upload, +.dropzone-previews .dz-preview .dz-progress .dz-upload { + display: block; + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 0%; + background-color: #8cc657; +} +.dropzone .dz-preview.dz-processing .dz-progress, +.dropzone-previews .dz-preview.dz-processing .dz-progress { + display: block; +} +.dropzone .dz-preview .dz-error-message, +.dropzone-previews .dz-preview .dz-error-message { + display: none; + position: absolute; + top: -5px; + left: -20px; + background: rgba(245,245,245,0.8); + padding: 8px 10px; + color: #800; + min-width: 140px; + max-width: 500px; + z-index: 500; +} +.dropzone .dz-preview:hover.dz-error .dz-error-message, +.dropzone-previews .dz-preview:hover.dz-error .dz-error-message { + display: block; +} +.dropzone { + border: 1px solid rgba(0,0,0,0.03); + min-height: 360px; + -webkit-border-radius: 3px; + border-radius: 3px; + background: rgba(0,0,0,0.03); + padding: 23px; +} +.dropzone .dz-default.dz-message { + opacity: 1; + -ms-filter: none; + filter: none; + -webkit-transition: opacity 0.3s ease-in-out; + -moz-transition: opacity 0.3s ease-in-out; + -o-transition: opacity 0.3s ease-in-out; + -ms-transition: opacity 0.3s ease-in-out; + transition: opacity 0.3s ease-in-out; + background-image: url("../images/spritemap.png"); + background-repeat: no-repeat; + background-position: 0 0; + position: absolute; + width: 428px; + height: 123px; + margin-left: -214px; + margin-top: -61.5px; + top: 50%; + left: 50%; +} +@media all and (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:1.5/1),(min-device-pixel-ratio:1.5),(min-resolution:138dpi),(min-resolution:1.5dppx) { + .dropzone .dz-default.dz-message { + background-image: url("../images/spritemap@2x.png"); + -webkit-background-size: 428px 406px; + -moz-background-size: 428px 406px; + background-size: 428px 406px; + } +} +.dropzone .dz-default.dz-message span { + display: none; +} +.dropzone.dz-square .dz-default.dz-message { + background-position: 0 -123px; + width: 268px; + margin-left: -134px; + height: 174px; + margin-top: -87px; +} +.dropzone.dz-drag-hover .dz-message { + opacity: 0.15; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=15)"; + filter: alpha(opacity=15); +} +.dropzone.dz-started .dz-message { + display: block; + opacity: 0; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; + filter: alpha(opacity=0); +} +.dropzone .dz-preview, +.dropzone-previews .dz-preview { + -webkit-box-shadow: 1px 1px 4px rgba(0,0,0,0.16); + box-shadow: 1px 1px 4px rgba(0,0,0,0.16); + font-size: 14px; +} +.dropzone .dz-preview.dz-image-preview:hover .dz-details img, +.dropzone-previews .dz-preview.dz-image-preview:hover .dz-details img { + display: block; + opacity: 0.1; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=10)"; + filter: alpha(opacity=10); +} +.dropzone .dz-preview.dz-success .dz-success-mark, +.dropzone-previews .dz-preview.dz-success .dz-success-mark { + opacity: 1; + -ms-filter: none; + filter: none; +} +.dropzone .dz-preview.dz-error .dz-error-mark, +.dropzone-previews .dz-preview.dz-error .dz-error-mark { + opacity: 1; + -ms-filter: none; + filter: none; +} +.dropzone .dz-preview.dz-error .dz-progress .dz-upload, +.dropzone-previews .dz-preview.dz-error .dz-progress .dz-upload { + background: #ee1e2d; +} +.dropzone .dz-preview .dz-error-mark, +.dropzone-previews .dz-preview .dz-error-mark, +.dropzone .dz-preview .dz-success-mark, +.dropzone-previews .dz-preview .dz-success-mark { + display: block; + opacity: 0; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; + filter: alpha(opacity=0); + -webkit-transition: opacity 0.4s ease-in-out; + -moz-transition: opacity 0.4s ease-in-out; + -o-transition: opacity 0.4s ease-in-out; + -ms-transition: opacity 0.4s ease-in-out; + transition: opacity 0.4s ease-in-out; + background-image: url("../images/spritemap.png"); + background-repeat: no-repeat; +} +@media all and (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:1.5/1),(min-device-pixel-ratio:1.5),(min-resolution:138dpi),(min-resolution:1.5dppx) { + .dropzone .dz-preview .dz-error-mark, + .dropzone-previews .dz-preview .dz-error-mark, + .dropzone .dz-preview .dz-success-mark, + .dropzone-previews .dz-preview .dz-success-mark { + background-image: url("../images/spritemap@2x.png"); + -webkit-background-size: 428px 406px; + -moz-background-size: 428px 406px; + background-size: 428px 406px; + } +} +.dropzone .dz-preview .dz-error-mark span, +.dropzone-previews .dz-preview .dz-error-mark span, +.dropzone .dz-preview .dz-success-mark span, +.dropzone-previews .dz-preview .dz-success-mark span { + display: none; +} +.dropzone .dz-preview .dz-error-mark, +.dropzone-previews .dz-preview .dz-error-mark { + background-position: -268px -123px; +} +.dropzone .dz-preview .dz-success-mark, +.dropzone-previews .dz-preview .dz-success-mark { + background-position: -268px -163px; +} +.dropzone .dz-preview .dz-progress .dz-upload, +.dropzone-previews .dz-preview .dz-progress .dz-upload { + -webkit-animation: loading 0.4s linear infinite; + -moz-animation: loading 0.4s linear infinite; + -o-animation: loading 0.4s linear infinite; + -ms-animation: loading 0.4s linear infinite; + animation: loading 0.4s linear infinite; + -webkit-transition: width 0.3s ease-in-out; + -moz-transition: width 0.3s ease-in-out; + -o-transition: width 0.3s ease-in-out; + -ms-transition: width 0.3s ease-in-out; + transition: width 0.3s ease-in-out; + -webkit-border-radius: 2px; + border-radius: 2px; + position: absolute; + top: 0; + left: 0; + width: 0%; + height: 100%; + background-image: url("../images/spritemap.png"); + background-repeat: repeat-x; + background-position: 0px -400px; +} +@media all and (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:1.5/1),(min-device-pixel-ratio:1.5),(min-resolution:138dpi),(min-resolution:1.5dppx) { + .dropzone .dz-preview .dz-progress .dz-upload, + .dropzone-previews .dz-preview .dz-progress .dz-upload { + background-image: url("../images/spritemap@2x.png"); + -webkit-background-size: 428px 406px; + -moz-background-size: 428px 406px; + background-size: 428px 406px; + } +} +.dropzone .dz-preview.dz-success .dz-progress, +.dropzone-previews .dz-preview.dz-success .dz-progress { + display: block; + opacity: 0; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; + filter: alpha(opacity=0); + -webkit-transition: opacity 0.4s ease-in-out; + -moz-transition: opacity 0.4s ease-in-out; + -o-transition: opacity 0.4s ease-in-out; + -ms-transition: opacity 0.4s ease-in-out; + transition: opacity 0.4s ease-in-out; +} +.dropzone .dz-preview .dz-error-message, +.dropzone-previews .dz-preview .dz-error-message { + display: block; + opacity: 0; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; + filter: alpha(opacity=0); + -webkit-transition: opacity 0.3s ease-in-out; + -moz-transition: opacity 0.3s ease-in-out; + -o-transition: opacity 0.3s ease-in-out; + -ms-transition: opacity 0.3s ease-in-out; + transition: opacity 0.3s ease-in-out; +} +.dropzone .dz-preview:hover.dz-error .dz-error-message, +.dropzone-previews .dz-preview:hover.dz-error .dz-error-message { + opacity: 1; + -ms-filter: none; + filter: none; +} +.dropzone a.dz-remove, +.dropzone-previews a.dz-remove { + background-image: -webkit-linear-gradient(top, #fafafa, #eee); + background-image: -moz-linear-gradient(top, #fafafa, #eee); + background-image: -o-linear-gradient(top, #fafafa, #eee); + background-image: -ms-linear-gradient(top, #fafafa, #eee); + background-image: linear-gradient(to bottom, #fafafa, #eee); + -webkit-border-radius: 2px; + border-radius: 2px; + border: 1px solid #eee; + text-decoration: none; + display: block; + padding: 4px 5px; + text-align: center; + color: #aaa; + margin-top: 26px; +} +.dropzone a.dz-remove:hover, +.dropzone-previews a.dz-remove:hover { + color: #666; +} +@-moz-keyframes loading { + 0% { + background-position: 0 -400px; + } + + 100% { + background-position: -7px -400px; + } +} +@-webkit-keyframes loading { + 0% { + background-position: 0 -400px; + } + + 100% { + background-position: -7px -400px; + } +} +@-o-keyframes loading { + 0% { + background-position: 0 -400px; + } + + 100% { + background-position: -7px -400px; + } +} +@-ms-keyframes loading { + 0% { + background-position: 0 -400px; + } + + 100% { + background-position: -7px -400px; + } +} +@keyframes loading { + 0% { + background-position: 0 -400px; + } + + 100% { + background-position: -7px -400px; + } +} diff --git a/static/css/plugins/fullcalendar/fullcalendar.css b/static/css/plugins/fullcalendar/fullcalendar.css new file mode 100644 index 000000000000..b2feb028e3ff --- /dev/null +++ b/static/css/plugins/fullcalendar/fullcalendar.css @@ -0,0 +1,977 @@ +/*! + * FullCalendar v2.2.0 Stylesheet + * Docs & License: http://arshaw.com/fullcalendar/ + * (c) 2013 Adam Shaw + */ + + +.fc { + direction: ltr; + text-align: left; +} + +.fc-rtl { + text-align: right; +} + +body .fc { /* extra precedence to overcome jqui */ + font-size: 1em; +} + + +/* Colors +--------------------------------------------------------------------------------------------------*/ + +.fc-unthemed th, +.fc-unthemed td, +.fc-unthemed hr, +.fc-unthemed thead, +.fc-unthemed tbody, +.fc-unthemed .fc-row, +.fc-unthemed .fc-popover { + border-color: #ddd; +} + +.fc-unthemed .fc-popover { + background-color: #fff; +} + +.fc-unthemed hr, +.fc-unthemed .fc-popover .fc-header { + background: #eee; +} + +.fc-unthemed .fc-popover .fc-header .fc-close { + color: #666; +} + +.fc-unthemed .fc-today { + background: #fcf8e3; +} + +.fc-highlight { /* when user is selecting cells */ + background: #bce8f1; + opacity: .3; + filter: alpha(opacity=30); /* for IE */ +} + +.fc-bgevent { /* default look for background events */ + background: rgb(143, 223, 130); + opacity: .3; + filter: alpha(opacity=30); /* for IE */ +} + +.fc-nonbusiness { /* default look for non-business-hours areas */ + /* will inherit .fc-bgevent's styles */ + background: #ccc; +} + + +/* Icons (inline elements with styled text that mock arrow icons) +--------------------------------------------------------------------------------------------------*/ + +.fc-icon { + display: inline-block; + font-size: 2em; + line-height: .5em; + height: .5em; /* will make the total height 1em */ + font-family: "Courier New", Courier, monospace; +} + +.fc-icon-left-single-arrow:after { + content: "\02039"; + font-weight: bold; +} + +.fc-icon-right-single-arrow:after { + content: "\0203A"; + font-weight: bold; +} + +.fc-icon-left-double-arrow:after { + content: "\000AB"; +} + +.fc-icon-right-double-arrow:after { + content: "\000BB"; +} + +.fc-icon-x:after { + content: "\000D7"; +} + + +/* Buttons (styled ',tClose:"Close (Esc)",tLoading:"Loading..."}},a.fn.magnificPopup=function(c){A();var d=a(this);if("string"==typeof c)if("open"===c){var e,f=u?d.data("magnificPopup"):d[0].magnificPopup,g=parseInt(arguments[1],10)||0;f.items?e=f.items[g]:(e=d,f.delegate&&(e=e.find(f.delegate)),e=e.eq(g)),b._openClick({mfpEl:e},d,f)}else b.isOpen&&b[c].apply(b,Array.prototype.slice.call(arguments,1));else c=a.extend(!0,{},c),u?d.data("magnificPopup",c):d[0].magnificPopup=c,b.addGroup(d,c);return d};var C,D,E,F="inline",G=function(){E&&(D.after(E.addClass(C)).detach(),E=null)};a.magnificPopup.registerModule(F,{options:{hiddenClass:"hide",markup:"",tNotFound:"Content not found"},proto:{initInline:function(){b.types.push(F),w(h+"."+F,function(){G()})},getInline:function(c,d){if(G(),c.src){var e=b.st.inline,f=a(c.src);if(f.length){var g=f[0].parentNode;g&&g.tagName&&(D||(C=e.hiddenClass,D=x(C),C="mfp-"+C),E=f.after(D).detach().removeClass(C)),b.updateStatus("ready")}else b.updateStatus("error",e.tNotFound),f=a("
");return c.inlineElement=f,f}return b.updateStatus("ready"),b._parseMarkup(d,{},c),d}}});var H,I="ajax",J=function(){H&&a(document.body).removeClass(H)},K=function(){J(),b.req&&b.req.abort()};a.magnificPopup.registerModule(I,{options:{settings:null,cursor:"mfp-ajax-cur",tError:'The content could not be loaded.'},proto:{initAjax:function(){b.types.push(I),H=b.st.ajax.cursor,w(h+"."+I,K),w("BeforeChange."+I,K)},getAjax:function(c){H&&a(document.body).addClass(H),b.updateStatus("loading");var d=a.extend({url:c.src,success:function(d,e,f){var g={data:d,xhr:f};y("ParseAjax",g),b.appendContent(a(g.data),I),c.finished=!0,J(),b._setFocus(),setTimeout(function(){b.wrap.addClass(q)},16),b.updateStatus("ready"),y("AjaxContentAdded")},error:function(){J(),c.finished=c.loadError=!0,b.updateStatus("error",b.st.ajax.tError.replace("%url%",c.src))}},b.st.ajax.settings);return b.req=a.ajax(d),""}}});var L,M=function(c){if(c.data&&void 0!==c.data.title)return c.data.title;var d=b.st.image.titleSrc;if(d){if(a.isFunction(d))return d.call(b,c);if(c.el)return c.el.attr(d)||""}return""};a.magnificPopup.registerModule("image",{options:{markup:'
',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:'The image could not be loaded.'},proto:{initImage:function(){var c=b.st.image,d=".image";b.types.push("image"),w(m+d,function(){"image"===b.currItem.type&&c.cursor&&a(document.body).addClass(c.cursor)}),w(h+d,function(){c.cursor&&a(document.body).removeClass(c.cursor),v.off("resize"+p)}),w("Resize"+d,b.resizeImage),b.isLowIE&&w("AfterChange",b.resizeImage)},resizeImage:function(){var a=b.currItem;if(a&&a.img&&b.st.image.verticalFit){var c=0;b.isLowIE&&(c=parseInt(a.img.css("padding-top"),10)+parseInt(a.img.css("padding-bottom"),10)),a.img.css("max-height",b.wH-c)}},_onImageHasSize:function(a){a.img&&(a.hasSize=!0,L&&clearInterval(L),a.isCheckingImgSize=!1,y("ImageHasSize",a),a.imgHidden&&(b.content&&b.content.removeClass("mfp-loading"),a.imgHidden=!1))},findImageSize:function(a){var c=0,d=a.img[0],e=function(f){L&&clearInterval(L),L=setInterval(function(){return d.naturalWidth>0?void b._onImageHasSize(a):(c>200&&clearInterval(L),c++,void(3===c?e(10):40===c?e(50):100===c&&e(500)))},f)};e(1)},getImage:function(c,d){var e=0,f=function(){c&&(c.img[0].complete?(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("ready")),c.hasSize=!0,c.loaded=!0,y("ImageLoadComplete")):(e++,200>e?setTimeout(f,100):g()))},g=function(){c&&(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("error",h.tError.replace("%url%",c.src))),c.hasSize=!0,c.loaded=!0,c.loadError=!0)},h=b.st.image,i=d.find(".mfp-img");if(i.length){var j=document.createElement("img");j.className="mfp-img",c.el&&c.el.find("img").length&&(j.alt=c.el.find("img").attr("alt")),c.img=a(j).on("load.mfploader",f).on("error.mfploader",g),j.src=c.src,i.is("img")&&(c.img=c.img.clone()),j=c.img[0],j.naturalWidth>0?c.hasSize=!0:j.width||(c.hasSize=!1)}return b._parseMarkup(d,{title:M(c),img_replaceWith:c.img},c),b.resizeImage(),c.hasSize?(L&&clearInterval(L),c.loadError?(d.addClass("mfp-loading"),b.updateStatus("error",h.tError.replace("%url%",c.src))):(d.removeClass("mfp-loading"),b.updateStatus("ready")),d):(b.updateStatus("loading"),c.loading=!0,c.hasSize||(c.imgHidden=!0,d.addClass("mfp-loading"),b.findImageSize(c)),d)}}});var N,O=function(){return void 0===N&&(N=void 0!==document.createElement("p").style.MozTransform),N};a.magnificPopup.registerModule("zoom",{options:{enabled:!1,easing:"ease-in-out",duration:300,opener:function(a){return a.is("img")?a:a.find("img")}},proto:{initZoom:function(){var a,c=b.st.zoom,d=".zoom";if(c.enabled&&b.supportsTransition){var e,f,g=c.duration,j=function(a){var b=a.clone().removeAttr("style").removeAttr("class").addClass("mfp-animated-image"),d="all "+c.duration/1e3+"s "+c.easing,e={position:"fixed",zIndex:9999,left:0,top:0,"-webkit-backface-visibility":"hidden"},f="transition";return e["-webkit-"+f]=e["-moz-"+f]=e["-o-"+f]=e[f]=d,b.css(e),b},k=function(){b.content.css("visibility","visible")};w("BuildControls"+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.content.css("visibility","hidden"),a=b._getItemToZoom(),!a)return void k();f=j(a),f.css(b._getOffset()),b.wrap.append(f),e=setTimeout(function(){f.css(b._getOffset(!0)),e=setTimeout(function(){k(),setTimeout(function(){f.remove(),a=f=null,y("ZoomAnimationEnded")},16)},g)},16)}}),w(i+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.st.removalDelay=g,!a){if(a=b._getItemToZoom(),!a)return;f=j(a)}f.css(b._getOffset(!0)),b.wrap.append(f),b.content.css("visibility","hidden"),setTimeout(function(){f.css(b._getOffset())},16)}}),w(h+d,function(){b._allowZoom()&&(k(),f&&f.remove(),a=null)})}},_allowZoom:function(){return"image"===b.currItem.type},_getItemToZoom:function(){return b.currItem.hasSize?b.currItem.img:!1},_getOffset:function(c){var d;d=c?b.currItem.img:b.st.zoom.opener(b.currItem.el||b.currItem);var e=d.offset(),f=parseInt(d.css("padding-top"),10),g=parseInt(d.css("padding-bottom"),10);e.top-=a(window).scrollTop()-f;var h={width:d.width(),height:(u?d.innerHeight():d[0].offsetHeight)-g-f};return O()?h["-moz-transform"]=h.transform="translate("+e.left+"px,"+e.top+"px)":(h.left=e.left,h.top=e.top),h}}});var P="iframe",Q="//about:blank",R=function(a){if(b.currTemplate[P]){var c=b.currTemplate[P].find("iframe");c.length&&(a||(c[0].src=Q),b.isIE8&&c.css("display",a?"block":"none"))}};a.magnificPopup.registerModule(P,{options:{markup:'
',srcAction:"iframe_src",patterns:{youtube:{index:"youtube.com",id:"v=",src:"//www.youtube.com/embed/%id%?autoplay=1"},vimeo:{index:"vimeo.com/",id:"/",src:"//player.vimeo.com/video/%id%?autoplay=1"},gmaps:{index:"//maps.google.",src:"%id%&output=embed"}}},proto:{initIframe:function(){b.types.push(P),w("BeforeChange",function(a,b,c){b!==c&&(b===P?R():c===P&&R(!0))}),w(h+"."+P,function(){R()})},getIframe:function(c,d){var e=c.src,f=b.st.iframe;a.each(f.patterns,function(){return e.indexOf(this.index)>-1?(this.id&&(e="string"==typeof this.id?e.substr(e.lastIndexOf(this.id)+this.id.length,e.length):this.id.call(this,e)),e=this.src.replace("%id%",e),!1):void 0});var g={};return f.srcAction&&(g[f.srcAction]=e),b._parseMarkup(d,g,c),b.updateStatus("ready"),d}}});var S=function(a){var c=b.items.length;return a>c-1?a-c:0>a?c+a:a},T=function(a,b,c){return a.replace(/%curr%/gi,b+1).replace(/%total%/gi,c)};a.magnificPopup.registerModule("gallery",{options:{enabled:!1,arrowMarkup:'',preload:[0,2],navigateByImgClick:!0,arrows:!0,tPrev:"Previous (Left arrow key)",tNext:"Next (Right arrow key)",tCounter:"%curr% of %total%"},proto:{initGallery:function(){var c=b.st.gallery,e=".mfp-gallery",g=Boolean(a.fn.mfpFastClick);return b.direction=!0,c&&c.enabled?(f+=" mfp-gallery",w(m+e,function(){c.navigateByImgClick&&b.wrap.on("click"+e,".mfp-img",function(){return b.items.length>1?(b.next(),!1):void 0}),d.on("keydown"+e,function(a){37===a.keyCode?b.prev():39===a.keyCode&&b.next()})}),w("UpdateStatus"+e,function(a,c){c.text&&(c.text=T(c.text,b.currItem.index,b.items.length))}),w(l+e,function(a,d,e,f){var g=b.items.length;e.counter=g>1?T(c.tCounter,f.index,g):""}),w("BuildControls"+e,function(){if(b.items.length>1&&c.arrows&&!b.arrowLeft){var d=c.arrowMarkup,e=b.arrowLeft=a(d.replace(/%title%/gi,c.tPrev).replace(/%dir%/gi,"left")).addClass(s),f=b.arrowRight=a(d.replace(/%title%/gi,c.tNext).replace(/%dir%/gi,"right")).addClass(s),h=g?"mfpFastClick":"click";e[h](function(){b.prev()}),f[h](function(){b.next()}),b.isIE7&&(x("b",e[0],!1,!0),x("a",e[0],!1,!0),x("b",f[0],!1,!0),x("a",f[0],!1,!0)),b.container.append(e.add(f))}}),w(n+e,function(){b._preloadTimeout&&clearTimeout(b._preloadTimeout),b._preloadTimeout=setTimeout(function(){b.preloadNearbyImages(),b._preloadTimeout=null},16)}),void w(h+e,function(){d.off(e),b.wrap.off("click"+e),b.arrowLeft&&g&&b.arrowLeft.add(b.arrowRight).destroyMfpFastClick(),b.arrowRight=b.arrowLeft=null})):!1},next:function(){b.direction=!0,b.index=S(b.index+1),b.updateItemHTML()},prev:function(){b.direction=!1,b.index=S(b.index-1),b.updateItemHTML()},goTo:function(a){b.direction=a>=b.index,b.index=a,b.updateItemHTML()},preloadNearbyImages:function(){var a,c=b.st.gallery.preload,d=Math.min(c[0],b.items.length),e=Math.min(c[1],b.items.length);for(a=1;a<=(b.direction?e:d);a++)b._preloadItem(b.index+a);for(a=1;a<=(b.direction?d:e);a++)b._preloadItem(b.index-a)},_preloadItem:function(c){if(c=S(c),!b.items[c].preloaded){var d=b.items[c];d.parsed||(d=b.parseEl(c)),y("LazyLoad",d),"image"===d.type&&(d.img=a('').on("load.mfploader",function(){d.hasSize=!0}).on("error.mfploader",function(){d.hasSize=!0,d.loadError=!0,y("LazyLoadError",d)}).attr("src",d.src)),d.preloaded=!0}}}});var U="retina";a.magnificPopup.registerModule(U,{options:{replaceSrc:function(a){return a.src.replace(/\.\w+$/,function(a){return"@2x"+a})},ratio:1},proto:{initRetina:function(){if(window.devicePixelRatio>1){var a=b.st.retina,c=a.ratio;c=isNaN(c)?c():c,c>1&&(w("ImageHasSize."+U,function(a,b){b.img.css({"max-width":b.img[0].naturalWidth/c,width:"100%"})}),w("ElementParse."+U,function(b,d){d.src=a.replaceSrc(d,c)}))}}}}),function(){var b=1e3,c="ontouchstart"in window,d=function(){v.off("touchmove"+f+" touchend"+f)},e="mfpFastClick",f="."+e;a.fn.mfpFastClick=function(e){return a(this).each(function(){var g,h=a(this);if(c){var i,j,k,l,m,n;h.on("touchstart"+f,function(a){l=!1,n=1,m=a.originalEvent?a.originalEvent.touches[0]:a.touches[0],j=m.clientX,k=m.clientY,v.on("touchmove"+f,function(a){m=a.originalEvent?a.originalEvent.touches:a.touches,n=m.length,m=m[0],(Math.abs(m.clientX-j)>10||Math.abs(m.clientY-k)>10)&&(l=!0,d())}).on("touchend"+f,function(a){d(),l||n>1||(g=!0,a.preventDefault(),clearTimeout(i),i=setTimeout(function(){g=!1},b),e())})})}h.on("click"+f,function(){g||e()})})},a.fn.destroyMfpFastClick=function(){a(this).off("touchstart"+f+" click"+f),c&&v.off("touchmove"+f+" touchend"+f)}}(),A()}); \ No newline at end of file diff --git a/static/js/mindmup-editabletable.js b/static/js/mindmup-editabletable.js new file mode 100644 index 000000000000..4ae1b9b0e9cb --- /dev/null +++ b/static/js/mindmup-editabletable.js @@ -0,0 +1,133 @@ +/*global $, window*/ +$.fn.editableTableWidget = function (options) { + 'use strict'; + return $(this).each(function () { + var buildDefaultOptions = function () { + var opts = $.extend({}, $.fn.editableTableWidget.defaultOptions); + opts.editor = opts.editor.clone(); + return opts; + }, + activeOptions = $.extend(buildDefaultOptions(), options), + ARROW_LEFT = 37, ARROW_UP = 38, ARROW_RIGHT = 39, ARROW_DOWN = 40, ENTER = 13, ESC = 27, TAB = 9, + element = $(this), + editor = activeOptions.editor.css('position', 'absolute').hide().appendTo(element.parent()), + active, + showEditor = function (select) { + active = element.find('td:focus'); + if (active.length) { + editor.val(active.text()) + .removeClass('error') + .show() + .offset(active.offset()) + .css(active.css(activeOptions.cloneProperties)) + .width(active.width()) + .height(active.height()) + .focus(); + if (select) { + editor.select(); + } + } + }, + setActiveText = function () { + var text = editor.val(), + evt = $.Event('change'), + originalContent; + if (active.text() === text || editor.hasClass('error')) { + return true; + } + originalContent = active.html(); + active.text(text).trigger(evt, text); + if (evt.result === false) { + active.html(originalContent); + } + }, + movement = function (element, keycode) { + if (keycode === ARROW_RIGHT) { + return element.next('td'); + } else if (keycode === ARROW_LEFT) { + return element.prev('td'); + } else if (keycode === ARROW_UP) { + return element.parent().prev().children().eq(element.index()); + } else if (keycode === ARROW_DOWN) { + return element.parent().next().children().eq(element.index()); + } + return []; + }; + editor.blur(function () { + setActiveText(); + editor.hide(); + }).keydown(function (e) { + if (e.which === ENTER) { + setActiveText(); + editor.hide(); + active.focus(); + e.preventDefault(); + e.stopPropagation(); + } else if (e.which === ESC) { + editor.val(active.text()); + e.preventDefault(); + e.stopPropagation(); + editor.hide(); + active.focus(); + } else if (e.which === TAB) { + active.focus(); + } else if (this.selectionEnd - this.selectionStart === this.value.length) { + var possibleMove = movement(active, e.which); + if (possibleMove.length > 0) { + possibleMove.focus(); + e.preventDefault(); + e.stopPropagation(); + } + } + }) + .on('input paste', function () { + var evt = $.Event('validate'); + active.trigger(evt, editor.val()); + if (evt.result === false) { + editor.addClass('error'); + } else { + editor.removeClass('error'); + } + }); + //element.on('click keypress dblclick', showEditor) + element.find("td:not([data-editable='false'])").on('click keypress dblclick', showEditor) + .css('cursor', 'pointer') + .keydown(function (e) { + var prevent = true, + possibleMove = movement($(e.target), e.which); + if (possibleMove.length > 0) { + possibleMove.focus(); + } else if (e.which === ENTER) { + showEditor(false); + } else if (e.which === 17 || e.which === 91 || e.which === 93) { + showEditor(true); + prevent = false; + } else { + prevent = false; + } + if (prevent) { + e.stopPropagation(); + e.preventDefault(); + } + }); + + //element.find('td').prop('tabindex', 1); + element.find("td:not([data-editable='false'])").prop('tabindex', 1); + + $(window).on('resize', function () { + if (editor.is(':visible')) { + editor.offset(active.offset()) + .width(active.width()) + .height(active.height()); + } + }); + }); + +}; +$.fn.editableTableWidget.defaultOptions = { + cloneProperties: ['padding', 'padding-top', 'padding-bottom', 'padding-left', 'padding-right', + 'text-align', 'font', 'font-size', 'font-family', 'font-weight', + 'border', 'border-top', 'border-bottom', 'border-left', 'border-right'], + editor: $('') +}; + diff --git a/static/js/plugins/fullcalendar/fullcalendar.min.js b/static/js/plugins/fullcalendar/fullcalendar.min.js new file mode 100644 index 000000000000..fcbf126f11d9 --- /dev/null +++ b/static/js/plugins/fullcalendar/fullcalendar.min.js @@ -0,0 +1,8 @@ +/*! + * FullCalendar v2.2.0 + * Docs & License: http://arshaw.com/fullcalendar/ + * (c) 2013 Adam Shaw + */ +(function(t){"function"==typeof define&&define.amd?define(["jquery","moment"],t):t(jQuery,moment)})(function(t,e){function n(t,e){return e.longDateFormat("LT").replace(":mm","(:mm)").replace(/(\Wmm)$/,"($1)").replace(/\s*a$/i,"t")}function i(t,e){var n=e.longDateFormat("L");return n=n.replace(/^Y+[^\w\s]*|[^\w\s]*Y+$/g,""),t.isRTL?n+=" ddd":n="ddd "+n,n}function r(t){s(Fe,t)}function s(e){function n(n,i){t.isPlainObject(i)&&t.isPlainObject(e[n])&&!o(n)?e[n]=s({},e[n],i):void 0!==i&&(e[n]=i)}for(var i=1;arguments.length>i;i++)t.each(arguments[i],n);return e}function o(t){return/(Time|Duration)$/.test(t)}function l(n,i){function r(t){var n=e.localeData||e.langData;return n.call(e,t)||n.call(e,"en")}function o(t){ne?u()&&(p(),f(t)):l()}function l(){ie=K.theme?"ui":"fc",n.addClass("fc"),K.isRTL?n.addClass("fc-rtl"):n.addClass("fc-ltr"),K.theme?n.addClass("ui-widget"):n.addClass("fc-unthemed"),ne=t("
").prependTo(n),te=new a(q,K),ee=te.render(),ee&&n.prepend(ee),h(K.defaultView),K.handleWindowResize&&(oe=_(v,K.windowResizeDelay),t(window).resize(oe))}function d(){re&&re.destroy(),te.destroy(),ne.remove(),n.removeClass("fc fc-ltr fc-rtl fc-unthemed ui-widget"),t(window).unbind("resize",oe)}function u(){return n.is(":visible")}function h(t){f(0,t)}function f(e,n){ue++,re&&n&&re.name!==n&&(te.deactivateButton(re.name),B(),re.start&&re.destroy(),re.el.remove(),re=null),!re&&n&&(re=new Ge[n](q),re.el=t("
").appendTo(ne),te.activateButton(n)),re&&(e&&(le=re.incrementDate(le,e)),re.start&&!e&&le.isWithin(re.intervalStart,re.intervalEnd)||u()&&(B(),re.start&&re.destroy(),re.render(le),I(),C(),H(),b())),I(),ue--}function g(t){return u()?(t&&m(),ue++,re.updateSize(!0),ue--,!0):void 0}function p(){u()&&m()}function m(){se="number"==typeof K.contentHeight?K.contentHeight:"number"==typeof K.height?K.height-(ee?ee.outerHeight(!0):0):Math.round(ne.width()/Math.max(K.aspectRatio,.5))}function v(t){!ue&&t.target===window&&re.start&&g(!0)&&re.trigger("windowResize",de)}function y(){S(),E()}function w(){u()&&(B(),re.destroyEvents(),re.renderEvents(he),I())}function S(){B(),re.destroyEvents(),I()}function b(){!K.lazyFetching||ae(re.start,re.end)?E():w()}function E(){ce(re.start,re.end)}function D(t){he=t,w()}function T(){w()}function C(){te.updateTitle(re.title)}function H(){var t=q.getNow();t.isWithin(re.intervalStart,re.intervalEnd)?te.disableButton("today"):te.enableButton("today")}function x(t,e){t=q.moment(t),e=e?q.moment(e):t.hasTime()?t.clone().add(q.defaultTimedEventDuration):t.clone().add(q.defaultAllDayEventDuration),re.select(t,e)}function k(){re&&re.unselect()}function R(){f(-1)}function P(){f(1)}function F(){le.add(-1,"years"),f()}function L(){le.add(1,"years"),f()}function G(){le=q.getNow(),f()}function N(t){le=q.moment(t),f()}function A(t){le.add(e.duration(t)),f()}function Y(t,e){var n,i;e&&void 0!==Ge[e]||(e=e||"day",n=te.getViewsWithButtons().join(" "),i=n.match(RegExp("\\w+"+z(e))),i||(i=n.match(/\w+Day/)),e=i?i[0]:"agendaDay"),le=t,h(e)}function V(){return le.clone()}function B(){ne.css({width:"100%",height:ne.height(),overflow:"hidden"})}function I(){ne.css({width:"",height:"",overflow:""})}function Z(){return q}function j(){return re}function X(t,e){return void 0===e?K[t]:(("height"==t||"contentHeight"==t||"aspectRatio"==t)&&(K[t]=e,g(!0)),void 0)}function $(t,e){return K[t]?K[t].apply(e||de,Array.prototype.slice.call(arguments,2)):void 0}var q=this;i=i||{};var U,K=s({},Fe,i);U=K.lang in Le?Le[K.lang]:Le[Fe.lang],U&&(K=s({},Fe,U,i)),K.isRTL&&(K=s({},Fe,ze,U||{},i)),q.options=K,q.render=o,q.destroy=d,q.refetchEvents=y,q.reportEvents=D,q.reportEventChange=T,q.rerenderEvents=w,q.changeView=h,q.select=x,q.unselect=k,q.prev=R,q.next=P,q.prevYear=F,q.nextYear=L,q.today=G,q.gotoDate=N,q.incrementDate=A,q.zoomTo=Y,q.getDate=V,q.getCalendar=Z,q.getView=j,q.option=X,q.trigger=$;var Q=M(r(K.lang));if(K.monthNames&&(Q._months=K.monthNames),K.monthNamesShort&&(Q._monthsShort=K.monthNamesShort),K.dayNames&&(Q._weekdays=K.dayNames),K.dayNamesShort&&(Q._weekdaysShort=K.dayNamesShort),null!=K.firstDay){var J=M(Q._week);J.dow=K.firstDay,Q._week=J}q.defaultAllDayEventDuration=e.duration(K.defaultAllDayEventDuration),q.defaultTimedEventDuration=e.duration(K.defaultTimedEventDuration),q.moment=function(){var t;return"local"===K.timezone?(t=_e.moment.apply(null,arguments),t.hasTime()&&t.local()):t="UTC"===K.timezone?_e.moment.utc.apply(null,arguments):_e.moment.parseZone.apply(null,arguments),"_locale"in t?t._locale=Q:t._lang=Q,t},q.getIsAmbigTimezone=function(){return"local"!==K.timezone&&"UTC"!==K.timezone},q.rezoneDate=function(t){return q.moment(t.toArray())},q.getNow=function(){var t=K.now;return"function"==typeof t&&(t=t()),q.moment(t)},q.calculateWeekNumber=function(t){var e=K.weekNumberCalculation;return"function"==typeof e?e(t):"local"===e?t.week():"ISO"===e.toUpperCase()?t.isoWeek():void 0},q.getEventEnd=function(t){return t.end?t.end.clone():q.getDefaultEventEnd(t.allDay,t.start)},q.getDefaultEventEnd=function(t,e){var n=e.clone();return t?n.stripTime().add(q.defaultAllDayEventDuration):n.add(q.defaultTimedEventDuration),q.getIsAmbigTimezone()&&n.stripZone(),n},q.formatRange=function(t,e,n){return"function"==typeof n&&(n=n.call(q,K,Q)),W(t,e,n,null,K.isRTL)},q.formatDate=function(t,e){return"function"==typeof e&&(e=e.call(q,K,Q)),O(t,e)},c.call(q,K);var te,ee,ne,ie,re,se,oe,le,ae=q.isFetchNeeded,ce=q.fetchEvents,de=n[0],ue=0,he=[];le=null!=K.defaultDate?q.moment(K.defaultDate):q.getNow(),q.getSuggestedViewHeight=function(){return void 0===se&&p(),se},q.isHeightAuto=function(){return"auto"===K.contentHeight||"auto"===K.height}}function a(e,n){function i(){var e=n.header;return f=n.theme?"ui":"fc",e?g=t("
").append(s("left")).append(s("right")).append(s("center")).append('
'):void 0}function r(){g.remove()}function s(i){var r=t('
'),s=n.header[i];return s&&t.each(s.split(" "),function(){var i,s=t(),o=!0;t.each(this.split(","),function(i,r){var l,a,c,d,u,h,g,m;"title"==r?(s=s.add(t("

 

")),o=!1):(e[r]?l=function(){e[r]()}:Ge[r]&&(l=function(){e.changeView(r)},p.push(r)),l&&(a=T(n.themeButtonIcons,r),c=T(n.buttonIcons,r),d=T(n.defaultButtonText,r),u=T(n.buttonText,r),h=u?F(u):a&&n.theme?"":c&&!n.theme?"":F(d||r),g=["fc-"+r+"-button",f+"-button",f+"-state-default"],m=t('").click(function(){m.hasClass(f+"-state-disabled")||(l(),(m.hasClass(f+"-state-active")||m.hasClass(f+"-state-disabled"))&&m.removeClass(f+"-state-hover"))}).mousedown(function(){m.not("."+f+"-state-active").not("."+f+"-state-disabled").addClass(f+"-state-down")}).mouseup(function(){m.removeClass(f+"-state-down")}).hover(function(){m.not("."+f+"-state-active").not("."+f+"-state-disabled").addClass(f+"-state-hover")},function(){m.removeClass(f+"-state-hover").removeClass(f+"-state-down")}),s=s.add(m)))}),o&&s.first().addClass(f+"-corner-left").end().last().addClass(f+"-corner-right").end(),s.length>1?(i=t("
"),o&&i.addClass("fc-button-group"),i.append(s),r.append(i)):r.append(s)}),r}function o(t){g.find("h2").text(t)}function l(t){g.find(".fc-"+t+"-button").addClass(f+"-state-active")}function a(t){g.find(".fc-"+t+"-button").removeClass(f+"-state-active")}function c(t){g.find(".fc-"+t+"-button").attr("disabled","disabled").addClass(f+"-state-disabled")}function d(t){g.find(".fc-"+t+"-button").removeAttr("disabled").removeClass(f+"-state-disabled")}function u(){return p}var h=this;h.render=i,h.destroy=r,h.updateTitle=o,h.activateButton=l,h.deactivateButton=a,h.disableButton=c,h.enableButton=d,h.getViewsWithButtons=u;var f,g=t(),p=[]}function c(n){function i(t,e){return!A||t.clone().stripZone()Y.clone().stripZone()}function r(t,e){A=t,Y=e,q=[];var n=++j,i=Z.length;X=i;for(var r=0;i>r;r++)s(Z[r],n)}function s(e,n){o(e,function(i){var r,s,o,l=t.isArray(e.events);if(n==j){if(i)for(r=0;i.length>r;r++)s=i[r],o=l?s:S(s,e),o&&q.push.apply(q,E(o));X--,X||B(q)}})}function o(e,i){var r,s,l=_e.sourceFetchers;for(r=0;l.length>r;r++){if(s=l[r].call(N,e,A.clone(),Y.clone(),n.timezone,i),s===!0)return;if("object"==typeof s)return o(s,i),void 0}var a=e.events;if(a)t.isFunction(a)?(y(),a.call(N,A.clone(),Y.clone(),n.timezone,function(t){i(t),w()})):t.isArray(a)?i(a):i();else{var c=e.url;if(c){var d,u=e.success,h=e.error,f=e.complete;d=t.isFunction(e.data)?e.data():e.data;var g=t.extend({},d||{}),p=P(e.startParam,n.startParam),m=P(e.endParam,n.endParam),v=P(e.timezoneParam,n.timezoneParam);p&&(g[p]=A.format()),m&&(g[m]=Y.format()),n.timezone&&"local"!=n.timezone&&(g[v]=n.timezone),y(),t.ajax(t.extend({},Ne,e,{data:g,success:function(e){e=e||[];var n=R(u,this,arguments);t.isArray(n)&&(e=n),i(e)},error:function(){R(h,this,arguments),i()},complete:function(){R(f,this,arguments),w()}}))}else i()}}function l(t){var e=a(t);e&&(Z.push(e),X++,s(e,j))}function a(e){var n,i,r=_e.sourceNormalizers;if(t.isFunction(e)||t.isArray(e)?n={events:e}:"string"==typeof e?n={url:e}:"object"==typeof e&&(n=t.extend({},e)),n){for(n.className?"string"==typeof n.className&&(n.className=n.className.split(/\s+/)):n.className=[],t.isArray(n.events)&&(n.origArray=n.events,n.events=t.map(n.events,function(t){return S(t,n)})),i=0;r.length>i;i++)r[i].call(N,n);return n}}function c(e){Z=t.grep(Z,function(t){return!u(t,e)}),q=t.grep(q,function(t){return!u(t.source,e)}),B(q)}function u(t,e){return t&&e&&h(t)==h(e)}function h(t){return("object"==typeof t?t.origArray||t.url||t.events:null)||t}function f(t){t.start=N.moment(t.start),t.end&&(t.end=N.moment(t.end)),D(t),g(t),B(q)}function g(t){var e,n,i,r;for(e=0;q.length>e;e++)if(n=q[e],n._id==t._id&&n!==t)for(i=0;U.length>i;i++)r=U[i],void 0!==t[r]&&(n[r]=t[r])}function p(t,e){var n,i,r,s=S(t);if(s){for(n=E(s),i=0;n.length>i;i++)r=n[i],r.source||(e&&(W.events.push(r),r.source=W),q.push(r));return B(q),n}return[]}function m(e){var n,i;for(null==e?e=function(){return!0}:t.isFunction(e)||(n=e+"",e=function(t){return t._id==n}),q=t.grep(q,e,!0),i=0;Z.length>i;i++)t.isArray(Z[i].events)&&(Z[i].events=t.grep(Z[i].events,e,!0));B(q)}function v(e){return t.isFunction(e)?t.grep(q,e):null!=e?(e+="",t.grep(q,function(t){return t._id==e})):q}function y(){$++||V("loading",null,!0,O())}function w(){--$||V("loading",null,!1,O())}function S(i,r){var s,o,l,a,c={};if(n.eventDataTransform&&(i=n.eventDataTransform(i)),r&&r.eventDataTransform&&(i=r.eventDataTransform(i)),t.extend(c,i),r&&(c.source=r),c._id=i._id||(void 0===i.id?"_fc"+Ae++:i.id+""),c.className=i.className?"string"==typeof i.className?i.className.split(/\s+/):i.className:[],s=i.start||i.date,o=i.end,k(s)&&(s=e.duration(s)),k(o)&&(o=e.duration(o)),i.dow||e.isDuration(s)||e.isDuration(o))c.start=s?e.duration(s):null,c.end=o?e.duration(o):null,c._recurring=!0;else{if(s&&(s=N.moment(s),!s.isValid()))return!1;if(o&&(o=N.moment(o),!o.isValid()))return!1;l=i.allDay,void 0===l&&(a=P(r?r.allDayDefault:void 0,n.allDayDefault),l=void 0!==a?a:!(s.hasTime()||o&&o.hasTime())),b(s,o,l,c)}return c}function b(t,e,i,r){i?(t.hasTime()&&t.stripTime(),e&&e.hasTime()&&e.stripTime()):(t.hasTime()||(t=N.rezoneDate(t)),e&&!e.hasTime()&&(e=N.rezoneDate(e))),r.allDay=i,r.start=t,r.end=e||null,n.forceEventDuration&&!r.end&&(r.end=I(r)),d(r)}function E(e){var n,i,r,s,o,l,a,c,d,u,h=[],f=A,g=Y;if(f&&g||(n=N.getView(),f=n.start,g=n.end),e)if(e._recurring){if(r=e.dow)for(i={},s=0;r.length>s;s++)i[r[s]]=!0;for(o=f.clone().stripTime();o.isBefore(g);)(!i||i[o.day()])&&(l=e.start,a=e.end,c=o.clone(),d=null,l&&(c=c.time(l)),a&&(d=o.clone().time(a)),u=t.extend({},e),b(c,d,!l&&!a,u),h.push(u)),o.add(1,"days")}else h.push(e);return h}function D(t,e,n){var i,r,s,o,l=t._allDay,a=t._start,c=t._end,d=!1;return e||n||(e=t.start,n=t.end),i=t.allDay!=l?t.allDay:!(e||n).hasTime(),i&&(e&&(e=e.clone().stripTime()),n&&(n=n.clone().stripTime())),e&&(r=i?C(e,a.clone().stripTime()):C(e,a)),i!=l?d=!0:n&&(s=C(n||N.getDefaultEventEnd(i,e||a),e||a).subtract(C(c||N.getDefaultEventEnd(l,a),a))),o=T(v(t._id),d,i,r,s),{dateDelta:r,durationDelta:s,undo:o}}function T(e,i,r,s,o){var l=N.getIsAmbigTimezone(),a=[];return t.each(e,function(t,e){var c=e._allDay,u=e._start,h=e._end,f=null!=r?r:c,g=u.clone(),p=!i&&h?h.clone():null;f?(g.stripTime(),p&&p.stripTime()):(g.hasTime()||(g=N.rezoneDate(g)),p&&!p.hasTime()&&(p=N.rezoneDate(p))),p||!n.forceEventDuration&&!+o||(p=N.getDefaultEventEnd(f,g)),g.add(s),p&&p.add(s).add(o),l&&(+s||+o)&&(g.stripZone(),p&&p.stripZone()),e.allDay=f,e.start=g,e.end=p,d(e),a.push(function(){e.allDay=c,e.start=u,e.end=h,d(e)})}),function(){for(var t=0;a.length>t;t++)a[t]()}}function H(){var e,i=n.businessHours,r={className:"fc-nonbusiness",start:"09:00",end:"17:00",dow:[1,2,3,4,5],rendering:"inverse-background"};return i&&(e="object"==typeof i?t.extend({},r,i):r),e?E(S(e)):[]}function x(t,e,i){var r=t.source||{},s=P(t.constraint,r.constraint,n.eventConstraint),o=P(t.overlap,r.overlap,n.eventOverlap);return L(e,i,s,o,t)}function M(t,e){return L(t,e,n.selectConstraint,n.selectOverlap)}function F(t,e,n){var i;return n&&(i=E(S(n))[0])?x(i,t,e):M(t,e)}function L(t,e,n,i,r){var s,o,l,a,c;if(t=t.clone().stripZone(),e=e.clone().stripZone(),null!=n){for(s=z(n),o=!1,l=0;s.length>l;l++)if(_(s[l],t,e)){o=!0;break}if(!o)return!1}for(l=0;q.length>l;l++)if(a=q[l],(!r||r._id!==a._id)&&G(a,t,e)){if(i===!1)return!1;if("function"==typeof i&&!i(a,r))return!1;if(r){if(c=P(a.overlap,(a.source||{}).overlap),c===!1)return!1;if("function"==typeof c&&!c(r,a))return!1}}return!0}function z(t){return"businessHours"===t?H():"object"==typeof t?E(S(t)):v(t)}function _(t,e,n){var i=t.start.clone().stripZone(),r=N.getEventEnd(t).stripZone();return e>=i&&r>=n}function G(t,e,n){var i=t.start.clone().stripZone(),r=N.getEventEnd(t).stripZone();return r>e&&n>i}var N=this;N.isFetchNeeded=i,N.fetchEvents=r,N.addEventSource=l,N.removeEventSource=c,N.updateEvent=f,N.renderEvent=p,N.removeEvents=m,N.clientEvents=v,N.mutateEvent=D;var A,Y,V=N.trigger,O=N.getView,B=N.reportEvents,I=N.getEventEnd,W={events:[]},Z=[W],j=0,X=0,$=0,q=[];t.each((n.events?[n.events]:[]).concat(n.eventSources||[]),function(t,e){var n=a(e);n&&Z.push(n)});var U=["title","url","allDay","className","editable","color","backgroundColor","borderColor","textColor"];N.getBusinessHoursEvents=H,N.isEventAllowedInRange=x,N.isSelectionAllowedInRange=M,N.isExternalDragAllowedInRange=F}function d(t){t._allDay=t.allDay,t._start=t.start.clone(),t._end=t.end?t.end.clone():null}function u(t,e){e.left&&t.css({"border-left-width":1,"margin-left":e.left-1}),e.right&&t.css({"border-right-width":1,"margin-right":e.right-1})}function h(t){t.css({"margin-left":"","margin-right":"","border-left-width":"","border-right-width":""})}function f(){t("body").addClass("fc-not-allowed")}function g(){t("body").removeClass("fc-not-allowed")}function p(e,n,i){var r=Math.floor(n/e.length),s=Math.floor(n-r*(e.length-1)),o=[],l=[],a=[],c=0;m(e),e.each(function(n,i){var d=n===e.length-1?s:r,u=t(i).outerHeight(!0);d>u?(o.push(i),l.push(u),a.push(t(i).height())):c+=u}),i&&(n-=c,r=Math.floor(n/o.length),s=Math.floor(n-r*(o.length-1))),t(o).each(function(e,n){var i=e===o.length-1?s:r,c=l[e],d=a[e],u=i-(c-d);i>c&&t(n).height(u)})}function m(t){t.height("")}function v(e){var n=0;return e.find("> *").each(function(e,i){var r=t(i).outerWidth();r>n&&(n=r)}),n++,e.width(n),n}function y(t,e){return t.height(e).addClass("fc-scroller"),t[0].scrollHeight-1>t[0].clientHeight?!0:(w(t),!1)}function w(t){t.height("").removeClass("fc-scroller")}function S(e){var n=e.css("position"),i=e.parents().filter(function(){var e=t(this);return/(auto|scroll)/.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==n&&i.length?i:t(e[0].ownerDocument||document)}function b(t){var e=t.offset().left,n=e+t.width(),i=t.children(),r=i.offset().left,s=r+i.outerWidth();return{left:r-e,right:n-s}}function E(t){return 1==t.which&&!t.ctrlKey}function D(t,e,n,i){var r,s,o,l;return e>n&&i>t?(t>=n?(r=t.clone(),o=!0):(r=n.clone(),o=!1),i>=e?(s=e.clone(),l=!0):(s=i.clone(),l=!1),{start:r,end:s,isStart:o,isEnd:l}):void 0}function T(t,e){if(t=t||{},void 0!==t[e])return t[e];for(var n,i=e.split(/(?=[A-Z])/),r=i.length-1;r>=0;r--)if(n=t[i[r].toLowerCase()],void 0!==n)return n;return t["default"]}function C(t,n){return e.duration({days:t.clone().stripTime().diff(n.clone().stripTime(),"days"),ms:t.time()-n.time()})}function H(t){return"[object Date]"===Object.prototype.toString.call(t)||t instanceof Date}function x(t,e){return t-e}function k(t){return/^\d+\:\d+(?:\:\d+\.?(?:\d{3})?)?$/.test(t)}function M(t){var e=function(){};return e.prototype=t,new e}function R(e,n,i){if(t.isFunction(e)&&(e=[e]),e){var r,s;for(r=0;e.length>r;r++)s=e[r].apply(n,i)||s;return s}}function P(){for(var t=0;arguments.length>t;t++)if(void 0!==arguments[t])return arguments[t]}function F(t){return(t+"").replace(/&/g,"&").replace(//g,">").replace(/'/g,"'").replace(/"/g,""").replace(/\n/g,"
")}function L(t){return t.replace(/&.*?;/g,"")}function z(t){return t.charAt(0).toUpperCase()+t.slice(1)}function _(t,e){var n,i,r,s,o=function(){var l=+new Date-s;e>l&&l>0?n=setTimeout(o,e-l):(n=null,t.apply(r,i),n||(r=i=null))};return function(){r=this,i=arguments,s=+new Date,n||(n=setTimeout(o,e))}}function G(n,i,r){var s,o,l,a,c=n[0],d=1==n.length&&"string"==typeof c;return e.isMoment(c)?(a=e.apply(null,n),A(c,a)):H(c)||void 0===c?a=e.apply(null,n):(s=!1,o=!1,d?Ie.test(c)?(c+="-01",n=[c],s=!0,o=!0):(l=We.exec(c))&&(s=!l[5],o=!0):t.isArray(c)&&(o=!0),a=i?e.utc.apply(e,n):e.apply(null,n),s?(a._ambigTime=!0,a._ambigZone=!0):r&&(o?a._ambigZone=!0:d&&a.zone(c))),a._fullCalendar=!0,a}function N(t,e){var n,i=[],r=!1,s=!1;for(n=0;t.length>n;n++)i.push(_e.moment.parseZone(t[n])),r=r||i[n]._ambigTime,s=s||i[n]._ambigZone;for(n=0;i.length>n;n++)r&&!e?i[n].stripTime():s&&i[n].stripZone();return i}function A(t,e){t._ambigTime?e._ambigTime=!0:e._ambigTime&&(e._ambigTime=!1),t._ambigZone?e._ambigZone=!0:e._ambigZone&&(e._ambigZone=!1)}function Y(t,e){t.year(e[0]||0).month(e[1]||0).date(e[2]||0).hours(e[3]||0).minutes(e[4]||0).seconds(e[5]||0).milliseconds(e[6]||0)}function V(t,e){return je.format.call(t,e)}function O(t,e){return B(t,X(e))}function B(t,e){var n,i="";for(n=0;e.length>n;n++)i+=I(t,e[n]);return i}function I(t,e){var n,i;return"string"==typeof e?e:(n=e.token)?Xe[n]?Xe[n](t):V(t,n):e.maybe&&(i=B(t,e.maybe),i.match(/[1-9]/))?i:""}function W(t,e,n,i,r){var s;return t=_e.moment.parseZone(t),e=_e.moment.parseZone(e),s=(t.localeData||t.lang).call(t),n=s.longDateFormat(n)||n,i=i||" - ",Z(t,e,X(n),i,r)}function Z(t,e,n,i,r){var s,o,l,a,c="",d="",u="",h="",f="";for(o=0;n.length>o&&(s=j(t,e,n[o]),s!==!1);o++)c+=s;for(l=n.length-1;l>o&&(s=j(t,e,n[l]),s!==!1);l--)d=s+d;for(a=o;l>=a;a++)u+=I(t,n[a]),h+=I(e,n[a]);return(u||h)&&(f=r?h+i+u:u+i+h),c+f+d}function j(t,e,n){var i,r;return"string"==typeof n?n:(i=n.token)&&(r=$e[i.charAt(0)],r&&t.isSame(e,r))?V(t,i):!1}function X(t){return t in qe?qe[t]:qe[t]=$(t)}function $(t){for(var e,n=[],i=/\[([^\]]*)\]|\(([^\)]*)\)|(LT|(\w)\4*o?)|([^\w\[\(]+)/g;e=i.exec(t);)e[1]?n.push(e[1]):e[2]?n.push({maybe:$(e[2])}):e[3]?n.push({token:e[3]}):e[5]&&n.push(e[5]);return n}function q(t){this.options=t||{}}function U(t){this.grid=t}function K(t){this.coordMaps=t}function Q(t,e){this.coordMap=t,this.options=e||{}}function J(t,e){return t||e?t&&e?t.grid===e.grid&&t.row===e.row&&t.col===e.col:!1:!0}function te(e,n){this.options=n=n||{},this.sourceEl=e,this.parentEl=n.parentEl?t(n.parentEl):e.parent()}function ee(t){this.view=t}function ne(t){ee.call(this,t),this.coordMap=new U(this),this.elsByFill={}}function ie(t){var e=se(t);return"background"===e||"inverse-background"===e}function re(t){return"inverse-background"===se(t)}function se(t){return P((t.source||{}).rendering,t.rendering)}function oe(t){var e,n,i={};for(e=0;t.length>e;e++)n=t[e],(i[n._id]||(i[n._id]=[])).push(n);return i}function le(t,e){return t.eventStartMS-e.eventStartMS}function ae(t,e){return t.eventStartMS-e.eventStartMS||e.eventDurationMS-t.eventDurationMS||e.event.allDay-t.event.allDay||(t.event.title||"").localeCompare(e.event.title)}function ce(t){ne.call(this,t)}function de(t,e){var n,i;for(n=0;e.length>n;n++)if(i=e[n],i.leftCol<=t.rightCol&&i.rightCol>=t.leftCol)return!0;return!1}function ue(t,e){return t.leftCol-e.leftCol}function he(t){ne.call(this,t)}function fe(t){var e,n,i;if(t.sort(ae),e=ge(t),pe(e),n=e[0]){for(i=0;n.length>i;i++)me(n[i]);for(i=0;n.length>i;i++)ve(n[i],0,0)}}function ge(t){var e,n,i,r=[];for(e=0;t.length>e;e++){for(n=t[e],i=0;r.length>i&&ye(n,r[i]).length;i++);n.level=i,(r[i]||(r[i]=[])).push(n)}return r}function pe(t){var e,n,i,r,s;for(e=0;t.length>e;e++)for(n=t[e],i=0;n.length>i;i++)for(r=n[i],r.forwardSegs=[],s=e+1;t.length>s;s++)ye(r,t[s],r.forwardSegs)}function me(t){var e,n,i=t.forwardSegs,r=0;if(void 0===t.forwardPressure){for(e=0;i.length>e;e++)n=i[e],me(n),r=Math.max(r,1+n.forwardPressure);t.forwardPressure=r}}function ve(t,e,n){var i,r=t.forwardSegs;if(void 0===t.forwardCoord)for(r.length?(r.sort(Se),ve(r[0],e+1,n),t.forwardCoord=r[0].backwardCoord):t.forwardCoord=1,t.backwardCoord=t.forwardCoord-(t.forwardCoord-n)/(e+1),i=0;r.length>i;i++)ve(r[i],0,t.forwardCoord)}function ye(t,e,n){n=n||[];for(var i=0;e.length>i;i++)we(t,e[i])&&n.push(e[i]);return n}function we(t,e){return t.bottom>e.top&&t.topd;d++){var u=d*i,h=u+i-1,f=Math.max(a,u),g=Math.min(c,h);if(g>=f){var m=S(f),v=S(g),b=[m.col,v.col].sort(),D=p(f)==o,T=p(g)+1==l;r.push({row:d,leftCol:b[0],rightCol:b[1],isStart:D,isEnd:T})}}return r}function E(t,e){var n,i,r=t.clone().stripTime();return e&&(n=e.clone().stripTime(),i=+e.time(),i&&i>=k&&n.add(1,"days")),(!e||r>=n)&&(n=r.clone().add(1,"days")),{start:r,end:n}}function D(t){var e=E(t.start,t.end);return e.end.diff(e.start,"days")>1}var C=this;C.calendar=n,C.opt=i,C.trigger=r,C.isEventDraggable=s,C.isEventResizable=l,C.eventDrop=a,C.eventResize=c;var H=n.reportEventChange,x=n.options,k=e.duration(x.nextDayThreshold);C.init(),C.getEventTimeText=function(t,e){var r,s;return"object"==typeof t&&"object"==typeof e?(r=t,s=e,e=arguments[2]):(r=t.start,s=t.end),e=e||i("timeFormat"),s&&i("displayEventEnd")?n.formatRange(r,s,e):n.formatDate(r,e)},C.isHiddenDay=d,C.skipHiddenDays=h,C.getCellsPerWeek=u,C.dateToCell=v,C.dateToDayOffset=y,C.dayOffsetToCellOffset=w,C.cellOffsetToCell=S,C.cellToDate=f,C.cellToCellOffset=g,C.cellOffsetToDayOffset=p,C.dayOffsetToDate=m,C.rangeToSegments=b,C.isMultiDayEvent=D;var M,R=i("hiddenDays")||[],F=[],L=[],z=[],_=i("isRTL");(function(){i("weekends")===!1&&R.push(0,6);for(var e=0,n=0;7>e;e++)L[e]=n,F[e]=-1!=t.inArray(e,R),F[e]||(z[n]=e,n++);if(M=n,!M)throw"invalid hiddenDays"})()}function Ee(n){var i,r,s,o,l=_e.dataAttrPrefix;return l&&(l+="-"),i=n.data(l+"event")||null,i&&(i="object"==typeof i?t.extend({},i):{},r=i.start,null==r&&(r=i.time),s=i.duration,o=i.stick,delete i.start,delete i.time,delete i.duration,delete i.stick),null==r&&(r=n.data(l+"start")),null==r&&(r=n.data(l+"time")),null==s&&(s=n.data(l+"duration")),null==o&&(o=n.data(l+"stick")),r=null!=r?e.duration(r):null,s=null!=s?e.duration(s):null,o=Boolean(o),{eventProps:i,startTime:r,duration:s,stick:o}}function De(t){be.call(this,t),this.dayGrid=new ce(this),this.coordMap=this.dayGrid.coordMap}function Te(t){De.call(this,t)}function Ce(t){De.call(this,t)}function He(t){De.call(this,t)}function xe(t,e){return e.longDateFormat("LT").replace(":mm","(:mm)").replace(/(\Wmm)$/,"($1)").replace(/\s*a$/i,"a")}function ke(t,e){return e.longDateFormat("LT").replace(/\s*a$/i,"")}function Me(t){be.call(this,t),this.timeGrid=new he(this),this.opt("allDaySlot")?(this.dayGrid=new ce(this),this.coordMap=new K([this.dayGrid.coordMap,this.timeGrid.coordMap])):this.coordMap=this.timeGrid.coordMap}function Re(t){Me.call(this,t)}function Pe(t){Me.call(this,t)}var Fe={lang:"en",defaultTimedEventDuration:"02:00:00",defaultAllDayEventDuration:{days:1},forceEventDuration:!1,nextDayThreshold:"09:00:00",defaultView:"month",aspectRatio:1.35,header:{left:"title",center:"",right:"today prev,next"},weekends:!0,weekNumbers:!1,weekNumberTitle:"W",weekNumberCalculation:"local",lazyFetching:!0,startParam:"start",endParam:"end",timezoneParam:"timezone",timezone:!1,titleFormat:{month:"MMMM YYYY",week:"ll",day:"LL"},columnFormat:{month:"ddd",week:i,day:"dddd"},timeFormat:{"default":n},displayEventEnd:{month:!1,basicWeek:!1,"default":!0},isRTL:!1,defaultButtonText:{prev:"prev",next:"next",prevYear:"prev year",nextYear:"next year",today:"today",month:"month",week:"week",day:"day"},buttonIcons:{prev:"left-single-arrow",next:"right-single-arrow",prevYear:"left-double-arrow",nextYear:"right-double-arrow"},theme:!1,themeButtonIcons:{prev:"circle-triangle-w",next:"circle-triangle-e",prevYear:"seek-prev",nextYear:"seek-next"},dragOpacity:.75,dragRevertDuration:500,dragScroll:!0,unselectAuto:!0,dropAccept:"*",eventLimit:!1,eventLimitText:"more",eventLimitClick:"popover",dayPopoverFormat:"LL",handleWindowResize:!0,windowResizeDelay:200},Le={en:{columnFormat:{week:"ddd M/D"},dayPopoverFormat:"dddd, MMMM D"}},ze={header:{left:"next,prev today",center:"",right:"title"},buttonIcons:{prev:"right-single-arrow",next:"left-single-arrow",prevYear:"right-double-arrow",nextYear:"left-double-arrow"},themeButtonIcons:{prev:"circle-triangle-e",next:"circle-triangle-w",nextYear:"seek-prev",prevYear:"seek-next"}},_e=t.fullCalendar={version:"2.2.0"},Ge=_e.views={};t.fn.fullCalendar=function(e){var n=Array.prototype.slice.call(arguments,1),i=this;return this.each(function(r,s){var o,a=t(s),c=a.data("fullCalendar");"string"==typeof e?c&&t.isFunction(c[e])&&(o=c[e].apply(c,n),r||(i=o),"destroy"===e&&a.removeData("fullCalendar")):c||(c=new l(a,e),a.data("fullCalendar",c),c.render())}),i},_e.langs=Le,_e.datepickerLang=function(e,n,i){var r=Le[e];r||(r=Le[e]={}),s(r,{isRTL:i.isRTL,weekNumberTitle:i.weekHeader,titleFormat:{month:i.showMonthAfterYear?"YYYY["+i.yearSuffix+"] MMMM":"MMMM YYYY["+i.yearSuffix+"]"},defaultButtonText:{prev:L(i.prevText),next:L(i.nextText),today:L(i.currentText)}}),t.datepicker&&(t.datepicker.regional[n]=t.datepicker.regional[e]=i,t.datepicker.regional.en=t.datepicker.regional[""],t.datepicker.setDefaults(i))},_e.lang=function(t,e){var n;e&&(n=Le[t],n||(n=Le[t]={}),s(n,e||{})),Fe.lang=t},_e.sourceNormalizers=[],_e.sourceFetchers=[];var Ne={dataType:"json",cache:!1},Ae=1,Ye=["sun","mon","tue","wed","thu","fri","sat"];_e.applyAll=R;var Ve,Oe,Be,Ie=/^\s*\d{4}-\d\d$/,We=/^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?)?$/,Ze=e.fn,je=t.extend({},Ze);_e.moment=function(){return G(arguments)},_e.moment.utc=function(){var t=G(arguments,!0);return t.hasTime()&&t.utc(),t},_e.moment.parseZone=function(){return G(arguments,!0,!0)},Ze.clone=function(){var t=je.clone.apply(this,arguments);return A(this,t),this._fullCalendar&&(t._fullCalendar=!0),t},Ze.time=function(t){if(!this._fullCalendar)return je.time.apply(this,arguments);if(null==t)return e.duration({hours:this.hours(),minutes:this.minutes(),seconds:this.seconds(),milliseconds:this.milliseconds()});this._ambigTime=!1,e.isDuration(t)||e.isMoment(t)||(t=e.duration(t));var n=0;return e.isDuration(t)&&(n=24*Math.floor(t.asDays())),this.hours(n+t.hours()).minutes(t.minutes()).seconds(t.seconds()).milliseconds(t.milliseconds())},Ze.stripTime=function(){var t=this.toArray();return this.utc(),Oe(this,t.slice(0,3)),this._ambigTime=!0,this._ambigZone=!0,this},Ze.hasTime=function(){return!this._ambigTime},Ze.stripZone=function(){var t=this.toArray(),e=this._ambigTime;return this.utc(),Oe(this,t),e&&(this._ambigTime=!0),this._ambigZone=!0,this},Ze.hasZone=function(){return!this._ambigZone},Ze.zone=function(t){return null!=t&&(this._ambigTime=!1,this._ambigZone=!1),je.zone.apply(this,arguments)},Ze.local=function(){var t=this.toArray(),e=this._ambigZone;return je.local.apply(this,arguments),e&&Be(this,t),this},Ze.format=function(){return this._fullCalendar&&arguments[0]?O(this,arguments[0]):this._ambigTime?V(this,"YYYY-MM-DD"):this._ambigZone?V(this,"YYYY-MM-DD[T]HH:mm:ss"):je.format.apply(this,arguments)},Ze.toISOString=function(){return this._ambigTime?V(this,"YYYY-MM-DD"):this._ambigZone?V(this,"YYYY-MM-DD[T]HH:mm:ss"):je.toISOString.apply(this,arguments)},Ze.isWithin=function(t,e){var n=N([this,t,e]);return n[0]>=n[1]&&n[0]').addClass(n.className||"").css({top:0,left:0}).append(n.content).appendTo(n.parentEl),this.el.on("click",".fc-close",function(){e.hide()}),n.autoHide&&t(document).on("mousedown",this.documentMousedownProxy=t.proxy(this,"documentMousedown"))},documentMousedown:function(e){this.el&&!t(e.target).closest(this.el).length&&this.hide()},destroy:function(){this.hide(),this.el&&(this.el.remove(),this.el=null),t(document).off("mousedown",this.documentMousedownProxy) +},position:function(){var e,n,i,r,s,o=this.options,l=this.el.offsetParent().offset(),a=this.el.outerWidth(),c=this.el.outerHeight(),d=t(window),u=S(this.el);r=o.top||0,s=void 0!==o.left?o.left:void 0!==o.right?o.right-a:0,u.is(window)||u.is(document)?(u=d,e=0,n=0):(i=u.offset(),e=i.top,n=i.left),e+=d.scrollTop(),n+=d.scrollLeft(),o.viewportConstrain!==!1&&(r=Math.min(r,e+u.outerHeight()-c-this.margin),r=Math.max(r,e+this.margin),s=Math.min(s,n+u.outerWidth()-a-this.margin),s=Math.max(s,n+this.margin)),this.el.css({top:r-l.top,left:s-l.left})},trigger:function(t){this.options[t]&&this.options[t].apply(this,Array.prototype.slice.call(arguments,1))}},U.prototype={grid:null,rows:null,cols:null,containerEl:null,minX:null,maxX:null,minY:null,maxY:null,build:function(){this.grid.buildCoords(this.rows=[],this.cols=[]),this.computeBounds()},getCell:function(t,e){var n,i=null,r=this.rows,s=this.cols,o=-1,l=-1;if(this.inBounds(t,e)){for(n=0;r.length>n;n++)if(e>=r[n][0]&&r[n][1]>e){o=n;break}for(n=0;s.length>n;n++)if(t>=s[n][0]&&s[n][1]>t){l=n;break}o>=0&&l>=0&&(i={row:o,col:l},i.grid=this.grid,i.date=this.grid.getCellDate(i))}return i},computeBounds:function(){var t;this.containerEl&&(t=this.containerEl.offset(),this.minX=t.left,this.maxX=t.left+this.containerEl.outerWidth(),this.minY=t.top,this.maxY=t.top+this.containerEl.outerHeight())},inBounds:function(t,e){return this.containerEl?t>=this.minX&&this.maxX>t&&e>=this.minY&&this.maxY>e:!0}},K.prototype={coordMaps:null,build:function(){var t,e=this.coordMaps;for(t=0;e.length>t;t++)e[t].build()},getCell:function(t,e){var n,i=this.coordMaps,r=null;for(n=0;i.length>n&&!r;n++)r=i[n].getCell(t,e);return r}},Q.prototype={coordMap:null,options:null,isListening:!1,isDragging:!1,origCell:null,origDate:null,cell:null,date:null,mouseX0:null,mouseY0:null,mousemoveProxy:null,mouseupProxy:null,scrollEl:null,scrollBounds:null,scrollTopVel:null,scrollLeftVel:null,scrollIntervalId:null,scrollHandlerProxy:null,scrollSensitivity:30,scrollSpeed:200,scrollIntervalMs:50,mousedown:function(t){E(t)&&(t.preventDefault(),this.startListening(t),this.options.distance||this.startDrag(t))},startListening:function(e){var n,i;this.isListening||(e&&this.options.scroll&&(n=S(t(e.target)),n.is(window)||n.is(document)||(this.scrollEl=n,this.scrollHandlerProxy=_(t.proxy(this,"scrollHandler"),100),this.scrollEl.on("scroll",this.scrollHandlerProxy))),this.computeCoords(),e&&(i=this.getCell(e),this.origCell=i,this.origDate=i?i.date:null,this.mouseX0=e.pageX,this.mouseY0=e.pageY),t(document).on("mousemove",this.mousemoveProxy=t.proxy(this,"mousemove")).on("mouseup",this.mouseupProxy=t.proxy(this,"mouseup")).on("selectstart",this.preventDefault),this.isListening=!0,this.trigger("listenStart",e))},computeCoords:function(){this.coordMap.build(),this.computeScrollBounds()},mousemove:function(t){var e,n;this.isDragging||(e=this.options.distance||1,n=Math.pow(t.pageX-this.mouseX0,2)+Math.pow(t.pageY-this.mouseY0,2),n>=e*e&&this.startDrag(t)),this.isDragging&&this.drag(t)},startDrag:function(t){var e;this.isListening||this.startListening(),this.isDragging||(this.isDragging=!0,this.trigger("dragStart",t),e=this.getCell(t),e&&this.cellOver(e,!0))},drag:function(t){var e;this.isDragging&&(e=this.getCell(t),J(e,this.cell)||(this.cell&&this.cellOut(),e&&this.cellOver(e)),this.dragScroll(t))},cellOver:function(t){this.cell=t,this.date=t.date,this.trigger("cellOver",t,t.date)},cellOut:function(){this.cell&&(this.trigger("cellOut",this.cell),this.cell=null,this.date=null)},mouseup:function(t){this.stopDrag(t),this.stopListening(t)},stopDrag:function(t){this.isDragging&&(this.stopScrolling(),this.trigger("dragStop",t),this.isDragging=!1)},stopListening:function(e){this.isListening&&(this.scrollEl&&(this.scrollEl.off("scroll",this.scrollHandlerProxy),this.scrollHandlerProxy=null),t(document).off("mousemove",this.mousemoveProxy).off("mouseup",this.mouseupProxy).off("selectstart",this.preventDefault),this.mousemoveProxy=null,this.mouseupProxy=null,this.isListening=!1,this.trigger("listenStop",e),this.origCell=this.cell=null,this.origDate=this.date=null)},getCell:function(t){return this.coordMap.getCell(t.pageX,t.pageY)},trigger:function(t){this.options[t]&&this.options[t].apply(this,Array.prototype.slice.call(arguments,1))},preventDefault:function(t){t.preventDefault()},computeScrollBounds:function(){var t,e=this.scrollEl;e&&(t=e.offset(),this.scrollBounds={top:t.top,left:t.left,bottom:t.top+e.outerHeight(),right:t.left+e.outerWidth()})},dragScroll:function(t){var e,n,i,r,s=this.scrollSensitivity,o=this.scrollBounds,l=0,a=0;o&&(e=(s-(t.pageY-o.top))/s,n=(s-(o.bottom-t.pageY))/s,i=(s-(t.pageX-o.left))/s,r=(s-(o.right-t.pageX))/s,e>=0&&1>=e?l=-1*e*this.scrollSpeed:n>=0&&1>=n&&(l=n*this.scrollSpeed),i>=0&&1>=i?a=-1*i*this.scrollSpeed:r>=0&&1>=r&&(a=r*this.scrollSpeed)),this.setScrollVel(l,a)},setScrollVel:function(e,n){this.scrollTopVel=e,this.scrollLeftVel=n,this.constrainScrollVel(),!this.scrollTopVel&&!this.scrollLeftVel||this.scrollIntervalId||(this.scrollIntervalId=setInterval(t.proxy(this,"scrollIntervalFunc"),this.scrollIntervalMs))},constrainScrollVel:function(){var t=this.scrollEl;0>this.scrollTopVel?0>=t.scrollTop()&&(this.scrollTopVel=0):this.scrollTopVel>0&&t.scrollTop()+t[0].clientHeight>=t[0].scrollHeight&&(this.scrollTopVel=0),0>this.scrollLeftVel?0>=t.scrollLeft()&&(this.scrollLeftVel=0):this.scrollLeftVel>0&&t.scrollLeft()+t[0].clientWidth>=t[0].scrollWidth&&(this.scrollLeftVel=0)},scrollIntervalFunc:function(){var t=this.scrollEl,e=this.scrollIntervalMs/1e3;this.scrollTopVel&&t.scrollTop(t.scrollTop()+this.scrollTopVel*e),this.scrollLeftVel&&t.scrollLeft(t.scrollLeft()+this.scrollLeftVel*e),this.constrainScrollVel(),this.scrollTopVel||this.scrollLeftVel||this.stopScrolling()},stopScrolling:function(){this.scrollIntervalId&&(clearInterval(this.scrollIntervalId),this.scrollIntervalId=null,this.computeCoords())},scrollHandler:function(){this.scrollIntervalId||this.computeCoords()}},te.prototype={options:null,sourceEl:null,el:null,parentEl:null,top0:null,left0:null,mouseY0:null,mouseX0:null,topDelta:null,leftDelta:null,mousemoveProxy:null,isFollowing:!1,isHidden:!1,isAnimating:!1,start:function(e){this.isFollowing||(this.isFollowing=!0,this.mouseY0=e.pageY,this.mouseX0=e.pageX,this.topDelta=0,this.leftDelta=0,this.isHidden||this.updatePosition(),t(document).on("mousemove",this.mousemoveProxy=t.proxy(this,"mousemove")))},stop:function(e,n){function i(){this.isAnimating=!1,r.destroyEl(),this.top0=this.left0=null,n&&n()}var r=this,s=this.options.revertDuration;this.isFollowing&&!this.isAnimating&&(this.isFollowing=!1,t(document).off("mousemove",this.mousemoveProxy),e&&s&&!this.isHidden?(this.isAnimating=!0,this.el.animate({top:this.top0,left:this.left0},{duration:s,complete:i})):i())},getEl:function(){var t=this.el;return t||(this.sourceEl.width(),t=this.el=this.sourceEl.clone().css({position:"absolute",visibility:"",display:this.isHidden?"none":"",margin:0,right:"auto",bottom:"auto",width:this.sourceEl.width(),height:this.sourceEl.height(),opacity:this.options.opacity||"",zIndex:this.options.zIndex}).appendTo(this.parentEl)),t},destroyEl:function(){this.el&&(this.el.remove(),this.el=null)},updatePosition:function(){var t,e;this.getEl(),null===this.top0&&(this.sourceEl.width(),t=this.sourceEl.offset(),e=this.el.offsetParent().offset(),this.top0=t.top-e.top,this.left0=t.left-e.left),this.el.css({top:this.top0+this.topDelta,left:this.left0+this.leftDelta})},mousemove:function(t){this.topDelta=t.pageY-this.mouseY0,this.leftDelta=t.pageX-this.mouseX0,this.isHidden||this.updatePosition()},hide:function(){this.isHidden||(this.isHidden=!0,this.el&&this.el.hide())},show:function(){this.isHidden&&(this.isHidden=!1,this.updatePosition(),this.getEl().show())}},ee.prototype={view:null,cellHtml:"",rowHtml:function(t,e){var n,i,r=this.view,s=this.getHtmlRenderer("cell",t),o="";for(e=e||0,n=0;r.colCnt>n;n++)i=r.cellToDate(e,n),o+=s(e,n,i);return o=this.bookendCells(o,t,e),""+o+""},bookendCells:function(t,e,n){var i=this.view,r=this.getHtmlRenderer("intro",e)(n||0),s=this.getHtmlRenderer("outro",e)(n||0),o=i.opt("isRTL"),l=o?s:r,a=o?r:s;return"string"==typeof t?l+t+a:t.prepend(l).append(a)},getHtmlRenderer:function(t,e){var n,i,r,s,o=this.view;return n=t+"Html",e&&(i=e+z(t)+"Html"),i&&(s=o[i])?r=o:i&&(s=this[i])?r=this:(s=o[n])?r=o:(s=this[n])&&(r=this),"function"==typeof s?function(){return s.apply(r,arguments)||""}:function(){return s||""}}},ne.prototype=M(ee.prototype),t.extend(ne.prototype,{el:null,coordMap:null,cellDuration:null,elsByFill:null,render:function(){this.bindHandlers()},destroy:function(){},buildCoords:function(){},getCellDate:function(){},getCellDayEl:function(){},rangeToSegs:function(){},bindHandlers:function(){var e=this;this.el.on("mousedown",function(n){t(n.target).is(".fc-event-container *, .fc-more")||t(n.target).closest(".fc-popover").length||e.dayMousedown(n)}),this.bindSegHandlers()},dayMousedown:function(t){var e,n,i,r=this,s=this.view,o=s.calendar,l=s.opt("selectable"),a=null,c=new Q(this.coordMap,{scroll:s.opt("dragScroll"),dragStart:function(){s.unselect()},cellOver:function(t,s){c.origDate&&(i=r.getCellDayEl(t),a=[s,c.origDate].sort(x),e=a[0],n=a[1].clone().add(r.cellDuration),l&&(o.isSelectionAllowedInRange(e,n)?r.renderSelection(e,n):(a=null,f())))},cellOut:function(){a=null,r.destroySelection(),g()},listenStop:function(t){a&&(a[0].isSame(a[1])&&s.trigger("dayClick",i[0],e,t),l&&s.reportSelection(e,n,t)),g()}});c.mousedown(t)},renderDrag:function(){},destroyDrag:function(){},renderResize:function(){},destroyResize:function(){},renderRangeHelper:function(t,e,n){var i,r=this.view;!e&&r.opt("forceEventDuration")&&(e=r.calendar.getDefaultEventEnd(!t.hasTime(),t)),i=n?M(n.event):{},i.start=t,i.end=e,i.allDay=!(t.hasTime()||e&&e.hasTime()),i.className=(i.className||[]).concat("fc-helper"),n||(i.editable=!1),this.renderHelper(i,n)},renderHelper:function(){},destroyHelper:function(){},renderSelection:function(t,e){this.renderHighlight(t,e)},destroySelection:function(){this.destroyHighlight()},renderHighlight:function(t,e){this.renderFill("highlight",this.rangeToSegs(t,e))},destroyHighlight:function(){this.destroyFill("highlight")},highlightSegClasses:function(){return["fc-highlight"]},renderFill:function(){},destroyFill:function(t){var e=this.elsByFill[t];e&&(e.remove(),delete this.elsByFill[t])},renderFillSegEls:function(e,n){var i,r=this,s=this[e+"SegEl"],o="",l=[];if(n.length){for(i=0;n.length>i;i++)o+=this.fillSegHtml(e,n[i]);t(o).each(function(e,i){var o=n[e],a=t(i);s&&(a=s.call(r,o,a)),a&&(a=t(a),a.is(r.fillSegTag)&&(o.el=a,l.push(o)))})}return l},fillSegTag:"div",fillSegHtml:function(t,e){var n=this[t+"SegClasses"],i=this[t+"SegStyles"],r=n?n.call(this,e):[],s=i?i.call(this,e):"";return"<"+this.fillSegTag+(r.length?' class="'+r.join(" ")+'"':"")+(s?' style="'+s+'"':"")+" />"},headHtml:function(){return'
'+""+""+this.rowHtml("head")+""+"
"+"
"},headCellHtml:function(t,e,n){var i=this.view,r=i.calendar,s=i.opt("columnFormat");return''+F(r.formatDate(n,s))+""},bgCellHtml:function(t,e,n){var i=this.view,r=this.getDayClasses(n);return r.unshift("fc-day",i.widgetContentClass),''},getDayClasses:function(t){var e=this.view,n=e.calendar.getNow().stripTime(),i=["fc-"+Ye[t.day()]];return"month"===e.name&&t.month()!=e.intervalStart.month()&&i.push("fc-other-month"),t.isSame(n,"day")?i.push("fc-today",e.highlightStateClass):n>t?i.push("fc-past"):i.push("fc-future"),i}}),t.extend(ne.prototype,{mousedOverSeg:null,isDraggingSeg:!1,isResizingSeg:!1,segs:null,renderEvents:function(t){var e,n,i=this.eventsToSegs(t),r=[],s=[];for(e=0;i.length>e;e++)n=i[e],ie(n.event)?r.push(n):s.push(n);r=this.renderBgSegs(r)||r,s=this.renderFgSegs(s)||s,this.segs=r.concat(s)},destroyEvents:function(){this.triggerSegMouseout(),this.destroyFgSegs(),this.destroyBgSegs(),this.segs=null},getSegs:function(){return this.segs||[]},renderFgSegs:function(){},destroyFgSegs:function(){},renderFgSegEls:function(e,n){var i,r=this.view,s="",o=[];if(e.length){for(i=0;e.length>i;i++)s+=this.fgSegHtml(e[i],n);t(s).each(function(n,i){var s=e[n],l=r.resolveEventEl(s.event,t(i));l&&(l.data("fc-seg",s),s.el=l,o.push(s))})}return o},fgSegHtml:function(){},renderBgSegs:function(t){return this.renderFill("bgEvent",t)},destroyBgSegs:function(){this.destroyFill("bgEvent")},bgEventSegEl:function(t,e){return this.view.resolveEventEl(t.event,e)},bgEventSegClasses:function(t){var e=t.event,n=e.source||{};return["fc-bgevent"].concat(e.className,n.className||[])},bgEventSegStyles:function(t){var e=this.view,n=t.event,i=n.source||{},r=n.color,s=i.color,o=e.opt("eventColor"),l=n.backgroundColor||r||i.backgroundColor||s||e.opt("eventBackgroundColor")||o;return l?"background-color:"+l:""},businessHoursSegClasses:function(){return["fc-nonbusiness","fc-bgevent"]},bindSegHandlers:function(){var e=this,n=this.view;t.each({mouseenter:function(t,n){e.triggerSegMouseover(t,n)},mouseleave:function(t,n){e.triggerSegMouseout(t,n)},click:function(t,e){return n.trigger("eventClick",this,t.event,e)},mousedown:function(i,r){t(r.target).is(".fc-resizer")&&n.isEventResizable(i.event)?e.segResizeMousedown(i,r):n.isEventDraggable(i.event)&&e.segDragMousedown(i,r)}},function(n,i){e.el.on(n,".fc-event-container > *",function(n){var r=t(this).data("fc-seg");return!r||e.isDraggingSeg||e.isResizingSeg?void 0:i.call(this,r,n)})})},triggerSegMouseover:function(t,e){this.mousedOverSeg||(this.mousedOverSeg=t,this.view.trigger("eventMouseover",t.el[0],t.event,e))},triggerSegMouseout:function(t,e){e=e||{},this.mousedOverSeg&&(t=t||this.mousedOverSeg,this.mousedOverSeg=null,this.view.trigger("eventMouseout",t.el[0],t.event,e))},segDragMousedown:function(t,e){var n,i,r=this,s=this.view,o=s.calendar,l=t.el,a=t.event,c=new te(t.el,{parentEl:s.el,opacity:s.opt("dragOpacity"),revertDuration:s.opt("dragRevertDuration"),zIndex:2}),d=new Q(s.coordMap,{distance:5,scroll:s.opt("dragScroll"),listenStart:function(t){c.hide(),c.start(t)},dragStart:function(e){r.triggerSegMouseout(t,e),r.isDraggingSeg=!0,s.hideEvent(a),s.trigger("eventDragStart",l[0],a,e,{})},cellOver:function(e,l){var u=t.cellDate||d.origDate,h=r.computeDraggedEventDates(t,u,l);n=h.start,i=h.end,o.isEventAllowedInRange(a,n,h.visibleEnd)?s.renderDrag(n,i,t)?c.hide():c.show():(n=null,c.show(),f())},cellOut:function(){n=null,s.destroyDrag(),c.show(),g()},dragStop:function(t){var e=n&&!n.isSame(a.start);c.stop(!e,function(){r.isDraggingSeg=!1,s.destroyDrag(),s.showEvent(a),s.trigger("eventDragStop",l[0],a,t,{}),e&&s.eventDrop(l[0],a,n,t)}),g()},listenStop:function(){c.stop()}});d.mousedown(e)},computeDraggedEventDates:function(t,e,n){var i,r,s,o,l,a=this.view,c=t.event,d=c.start,u=a.calendar.getEventEnd(c);return n.hasTime()===e.hasTime()?(i=C(n,e),r=d.clone().add(i),s=null===c.end?null:u.clone().add(i),o=c.allDay):(r=n,s=null,o=!n.hasTime()),l=s||a.calendar.getDefaultEventEnd(o,r),{start:r,end:s,visibleEnd:l}},segResizeMousedown:function(t,e){function n(){r.destroyResize(),s.showEvent(a)}var i,r=this,s=this.view,o=s.calendar,l=t.el,a=t.event,c=a.start,d=s.calendar.getEventEnd(a),u=null;i=new Q(this.coordMap,{distance:5,scroll:s.opt("dragScroll"),dragStart:function(e){r.triggerSegMouseout(t,e),r.isResizingSeg=!0,s.trigger("eventResizeStart",l[0],a,e,{})},cellOver:function(e,i){i.isBefore(c)&&(i=c),u=i.clone().add(r.cellDuration),o.isEventAllowedInRange(a,c,u)?u.isSame(d)?(u=null,n()):(r.renderResize(c,u,t),s.hideEvent(a)):(u=null,n(),f())},cellOut:function(){u=null,n(),g()},dragStop:function(t){r.isResizingSeg=!1,n(),g(),s.trigger("eventResizeStop",l[0],a,t,{}),u&&s.eventResize(l[0],a,u,t)}}),i.mousedown(e)},getSegClasses:function(t,e,n){var i=t.event,r=["fc-event",t.isStart?"fc-start":"fc-not-start",t.isEnd?"fc-end":"fc-not-end"].concat(i.className,i.source?i.source.className:[]);return e&&r.push("fc-draggable"),n&&r.push("fc-resizable"),r},getEventSkinCss:function(t){var e=this.view,n=t.source||{},i=t.color,r=n.color,s=e.opt("eventColor"),o=t.backgroundColor||i||n.backgroundColor||r||e.opt("eventBackgroundColor")||s,l=t.borderColor||i||n.borderColor||r||e.opt("eventBorderColor")||s,a=t.textColor||n.textColor||e.opt("eventTextColor"),c=[];return o&&c.push("background-color:"+o),l&&c.push("border-color:"+l),a&&c.push("color:"+a),c.join(";")},eventsToSegs:function(t,e){var n,i=this.eventsToRanges(t),r=[];for(n=0;i.length>n;n++)r.push.apply(r,this.eventRangeToSegs(i[n],e));return r},eventsToRanges:function(e){var n=this,i=oe(e),r=[];return t.each(i,function(t,e){e.length&&r.push.apply(r,re(e[0])?n.eventsToInverseRanges(e):n.eventsToNormalRanges(e))}),r},eventsToNormalRanges:function(t){var e,n,i,r,s=this.view.calendar,o=[];for(e=0;t.length>e;e++)n=t[e],i=n.start.clone().stripZone(),r=s.getEventEnd(n).stripZone(),o.push({event:n,start:i,end:r,eventStartMS:+i,eventDurationMS:r-i});return o},eventsToInverseRanges:function(t){var e,n,i=this.view,r=i.start.clone().stripZone(),s=i.end.clone().stripZone(),o=this.eventsToNormalRanges(t),l=[],a=t[0],c=r;for(o.sort(le),e=0;o.length>e;e++)n=o[e],n.start>c&&l.push({event:a,start:c,end:n.start}),c=n.end;return s>c&&l.push({event:a,start:c,end:s}),l},eventRangeToSegs:function(t,e){var n,i,r;for(n=e?e(t.start,t.end):this.rangeToSegs(t.start,t.end),i=0;n.length>i;i++)r=n[i],r.event=t.event,r.eventStartMS=t.eventStartMS,r.eventDurationMS=t.eventDurationMS;return n}}),ce.prototype=M(ne.prototype),t.extend(ce.prototype,{numbersVisible:!1,cellDuration:e.duration({days:1}),bottomCoordPadding:0,rowEls:null,dayEls:null,helperEls:null,render:function(e){var n,i=this.view,r="";for(n=0;i.rowCnt>n;n++)r+=this.dayRowHtml(n,e);this.el.html(r),this.rowEls=this.el.find(".fc-row"),this.dayEls=this.el.find(".fc-day"),this.dayEls.each(function(e,n){var r=i.cellToDate(Math.floor(e/i.colCnt),e%i.colCnt);i.trigger("dayRender",null,r,t(n))}),ne.prototype.render.call(this)},destroy:function(){this.destroySegPopover()},dayRowHtml:function(t,e){var n=this.view,i=["fc-row","fc-week",n.widgetContentClass];return e&&i.push("fc-rigid"),'
'+'
'+""+this.rowHtml("day",t)+"
"+"
"+'
'+""+(this.numbersVisible?""+this.rowHtml("number",t)+"":"")+"
"+"
"+"
"},dayCellHtml:function(t,e,n){return this.bgCellHtml(t,e,n)},buildCoords:function(e,n){var i,r,s,o=this.view.colCnt;this.dayEls.slice(0,o).each(function(e,o){i=t(o),r=i.offset().left,e&&(s[1]=r),s=[r],n[e]=s}),s[1]=r+i.outerWidth(),this.rowEls.each(function(n,o){i=t(o),r=i.offset().top,n&&(s[1]=r),s=[r],e[n]=s}),s[1]=r+i.outerHeight()+this.bottomCoordPadding},getCellDate:function(t){return this.view.cellToDate(t)},getCellDayEl:function(t){return this.dayEls.eq(t.row*this.view.colCnt+t.col)},rangeToSegs:function(t,e){return this.view.rangeToSegments(t,e)},renderDrag:function(t,e,n){var i;return this.renderHighlight(t,e||this.view.calendar.getDefaultEventEnd(!0,t)),n&&!n.el.closest(this.el).length?(this.renderRangeHelper(t,e,n),i=this.view.opt("dragOpacity"),void 0!==i&&this.helperEls.css("opacity",i),!0):void 0},destroyDrag:function(){this.destroyHighlight(),this.destroyHelper()},renderResize:function(t,e,n){this.renderHighlight(t,e),this.renderRangeHelper(t,e,n)},destroyResize:function(){this.destroyHighlight(),this.destroyHelper()},renderHelper:function(e,n){var i,r=[],s=this.eventsToSegs([e]);s=this.renderFgSegEls(s),i=this.renderSegRows(s),this.rowEls.each(function(e,s){var o,l=t(s),a=t('
');o=n&&n.row===e?n.el.position().top:l.find(".fc-content-skeleton tbody").position().top,a.css("top",o).find("table").append(i[e].tbodyEl),l.append(a),r.push(a[0])}),this.helperEls=t(r)},destroyHelper:function(){this.helperEls&&(this.helperEls.remove(),this.helperEls=null)},fillSegTag:"td",renderFill:function(e,n){var i,r,s,o=[];for(n=this.renderFillSegEls(e,n),i=0;n.length>i;i++)r=n[i],s=this.renderFillRow(e,r),this.rowEls.eq(r.row).append(s),o.push(s[0]);return this.elsByFill[e]=t(o),n},renderFillRow:function(e,n){var i,r,s=this.view.colCnt,o=n.leftCol,l=n.rightCol+1;return i=t('
'+"
"+"
"),r=i.find("tr"),o>0&&r.append(''),r.append(n.el.attr("colspan",l-o)),s>l&&r.append(''),this.bookendCells(r,e),i}}),t.extend(ce.prototype,{rowStructs:null,destroyEvents:function(){this.destroySegPopover(),ne.prototype.destroyEvents.apply(this,arguments)},getSegs:function(){return ne.prototype.getSegs.call(this).concat(this.popoverSegs||[])},renderBgSegs:function(e){var n=t.grep(e,function(t){return t.event.allDay});return ne.prototype.renderBgSegs.call(this,n)},renderFgSegs:function(e){var n;return e=this.renderFgSegEls(e),n=this.rowStructs=this.renderSegRows(e),this.rowEls.each(function(e,i){t(i).find(".fc-content-skeleton > table").append(n[e].tbodyEl)}),e},destroyFgSegs:function(){for(var t,e=this.rowStructs||[];t=e.pop();)t.tbodyEl.remove();this.rowStructs=null},renderSegRows:function(t){var e,n,i=[];for(e=this.groupSegRows(t),n=0;e.length>n;n++)i.push(this.renderSegRow(n,e[n]));return i},fgSegHtml:function(t,e){var n,i=this.view,r=i.opt("isRTL"),s=t.event,o=i.isEventDraggable(s),l=!e&&s.allDay&&t.isEnd&&i.isEventResizable(s),a=this.getSegClasses(t,o,l),c=this.getEventSkinCss(s),d="";return a.unshift("fc-day-grid-event"),!s.allDay&&t.isStart&&(d=''+F(i.getEventTimeText(s))+""),n=''+(F(s.title||"")||" ")+"",'"+'
'+(r?n+" "+d:d+" "+n)+"
"+(l?'
':"")+""},renderSegRow:function(e,n){function i(e){for(;e>o;)d=(y[r-1]||[])[o],d?d.attr("rowspan",parseInt(d.attr("rowspan")||1,10)+1):(d=t(""),l.append(d)),v[r][o]=d,y[r][o]=d,o++}var r,s,o,l,a,c,d,u=this.view,h=u.colCnt,f=this.buildSegLevels(n),g=Math.max(1,f.length),p=t(""),m=[],v=[],y=[];for(r=0;g>r;r++){if(s=f[r],o=0,l=t(""),m.push([]),v.push([]),y.push([]),s)for(a=0;s.length>a;a++){for(c=s[a],i(c.leftCol),d=t('').append(c.el),c.leftCol!=c.rightCol?d.attr("colspan",c.rightCol-c.leftCol+1):y[r][o]=d;c.rightCol>=o;)v[r][o]=d,m[r][o]=c,o++;l.append(d)}i(h),this.bookendCells(l,"eventSkeleton"),p.append(l)}return{row:e,tbodyEl:p,cellMatrix:v,segMatrix:m,segLevels:f,segs:n}},buildSegLevels:function(t){var e,n,i,r=[];for(t.sort(ae),e=0;t.length>e;e++){for(n=t[e],i=0;r.length>i&&de(n,r[i]);i++);n.level=i,(r[i]||(r[i]=[])).push(n)}for(i=0;r.length>i;i++)r[i].sort(ue);return r},groupSegRows:function(t){var e,n=this.view,i=[];for(e=0;n.rowCnt>e;e++)i.push([]);for(e=0;t.length>e;e++)i[t[e].row].push(t[e]);return i}}),t.extend(ce.prototype,{segPopover:null,popoverSegs:null,destroySegPopover:function(){this.segPopover&&this.segPopover.hide()},limitRows:function(t){var e,n,i=this.rowStructs||[];for(e=0;i.length>e;e++)this.unlimitRow(e),n=t?"number"==typeof t?t:this.computeRowLevelLimit(e):!1,n!==!1&&this.limitRow(e,n)},computeRowLevelLimit:function(t){var e,n,i=this.rowEls.eq(t),r=i.height(),s=this.rowStructs[t].tbodyEl.children();for(e=0;s.length>e;e++)if(n=s.eq(e).removeClass("fc-limited"),n.position().top+n.outerHeight()>r)return e;return!1},limitRow:function(e,n){function i(i){for(;i>T;)r={row:e,col:T},d=S.getCellSegs(r,n),d.length&&(f=o[n-1][T],w=S.renderMoreLink(r,d),y=t("
").append(w),f.append(y),D.push(y[0])),T++}var r,s,o,l,a,c,d,u,h,f,g,p,m,v,y,w,S=this,b=this.view,E=this.rowStructs[e],D=[],T=0;if(n&&E.segLevels.length>n){for(s=E.segLevels[n-1],o=E.cellMatrix,l=E.tbodyEl.children().slice(n).addClass("fc-limited").get(),a=0;s.length>a;a++){for(c=s[a],i(c.leftCol),h=[],u=0;c.rightCol>=T;)r={row:e,col:T},d=this.getCellSegs(r,n),h.push(d),u+=d.length,T++;if(u){for(f=o[n-1][c.leftCol],g=f.attr("rowspan")||1,p=[],m=0;h.length>m;m++)v=t('').attr("rowspan",g),d=h[m],r={row:e,col:c.leftCol+m},w=this.renderMoreLink(r,[c].concat(d)),y=t("
").append(w),v.append(y),p.push(v[0]),D.push(v[0]);f.addClass("fc-limited").after(t(p)),l.push(f[0])}}i(b.colCnt),E.moreEls=t(D),E.limitedEls=t(l)}},unlimitRow:function(t){var e=this.rowStructs[t];e.moreEls&&(e.moreEls.remove(),e.moreEls=null),e.limitedEls&&(e.limitedEls.removeClass("fc-limited"),e.limitedEls=null)},renderMoreLink:function(e,n){var i=this,r=this.view;return t('').text(this.getMoreLinkText(n.length)).on("click",function(s){var o=r.opt("eventLimitClick"),l=r.cellToDate(e),a=t(this),c=i.getCellDayEl(e),d=i.getCellSegs(e),u=i.resliceDaySegs(d,l),h=i.resliceDaySegs(n,l);"function"==typeof o&&(o=r.trigger("eventLimitClick",null,{date:l,dayEl:c,moreEl:a,segs:u,hiddenSegs:h},s)),"popover"===o?i.showSegPopover(l,e,a,u):"string"==typeof o&&r.calendar.zoomTo(l,o)})},showSegPopover:function(t,e,n,i){var r,s,o=this,l=this.view,a=n.parent();r=1==l.rowCnt?this.view.el:this.rowEls.eq(e.row),s={className:"fc-more-popover",content:this.renderSegPopoverContent(t,i),parentEl:this.el,top:r.offset().top,autoHide:!0,viewportConstrain:l.opt("popoverViewportConstrain"),hide:function(){o.segPopover.destroy(),o.segPopover=null,o.popoverSegs=null}},l.opt("isRTL")?s.right=a.offset().left+a.outerWidth()+1:s.left=a.offset().left-1,this.segPopover=new q(s),this.segPopover.show()},renderSegPopoverContent:function(e,n){var i,r=this.view,s=r.opt("theme"),o=e.format(r.opt("dayPopoverFormat")),l=t('
'+''+''+F(o)+""+'
'+"
"+'
'+'
'+"
"),a=l.find(".fc-event-container");for(n=this.renderFgSegEls(n,!0),this.popoverSegs=n,i=0;n.length>i;i++)n[i].cellDate=e,a.append(n[i].el);return l},resliceDaySegs:function(e,n){var i=t.map(e,function(t){return t.event}),r=n.clone().stripTime(),s=r.clone().add(1,"days");return this.eventsToSegs(i,function(t,e){var n=D(t,e,r,s);return n?[n]:[]})},getMoreLinkText:function(t){var e=this.view,n=e.opt("eventLimitText");return"function"==typeof n?n(t):"+"+t+" "+n},getCellSegs:function(t,e){for(var n,i=this.rowStructs[t.row].segMatrix,r=e||0,s=[];i.length>r;)n=i[r][t.col],n&&s.push(n),r++;return s}}),he.prototype=M(ne.prototype),t.extend(he.prototype,{slotDuration:null,snapDuration:null,minTime:null,maxTime:null,dayEls:null,slatEls:null,slatTops:null,helperEl:null,businessHourSegs:null,render:function(){this.processOptions(),this.el.html(this.renderHtml()),this.dayEls=this.el.find(".fc-day"),this.slatEls=this.el.find(".fc-slats tr"),this.computeSlatTops(),this.renderBusinessHours(),ne.prototype.render.call(this)},renderBusinessHours:function(){var t=this.view.calendar.getBusinessHoursEvents();this.businessHourSegs=this.renderFill("businessHours",this.eventsToSegs(t),"bgevent")},renderHtml:function(){return'
'+this.rowHtml("slotBg")+"
"+"
"+'
'+""+this.slatRowHtml()+"
"+"
"},slotBgCellHtml:function(t,e,n){return this.bgCellHtml(t,e,n)},slatRowHtml:function(){for(var t,n,i,r=this.view,s=r.calendar,o=r.opt("isRTL"),l="",a=0===this.slotDuration.asMinutes()%15,c=e.duration(+this.minTime);this.maxTime>c;)t=r.start.clone().time(c),n=t.minutes(),i='"+(a&&n?"":""+F(s.formatDate(t,r.opt("axisFormat")))+"")+"",l+=""+(o?"":i)+''+(o?i:"")+"",c.add(this.slotDuration);return l},processOptions:function(){var t=this.view,n=t.opt("slotDuration"),i=t.opt("snapDuration");n=e.duration(n),i=i?e.duration(i):n,this.slotDuration=n,this.snapDuration=i,this.cellDuration=i,this.minTime=e.duration(t.opt("minTime")),this.maxTime=e.duration(t.opt("maxTime"))},rangeToSegs:function(t,e){var n,i,r,s,o,l=this.view,a=[];for(t=t.clone().stripZone(),e=e.clone().stripZone(),i=0;l.colCnt>i;i++)r=l.cellToDate(0,i),s=r.clone().time(this.minTime),o=r.clone().time(this.maxTime),n=D(t,e,s,o),n&&(n.col=i,a.push(n));return a},resize:function(){this.computeSlatTops(),this.updateSegVerticals()},buildCoords:function(n,i){var r,s,o=this.view.colCnt,l=this.el.offset().top,a=e.duration(+this.minTime),c=null;for(this.dayEls.slice(0,o).each(function(e,n){r=t(n),s=r.offset().left,c&&(c[1]=s),c=[s],i[e]=c}),c[1]=s+r.outerWidth(),c=null;this.maxTime>a;)s=l+this.computeTimeTop(a),c&&(c[1]=s),c=[s],n.push(c),a.add(this.snapDuration);c[1]=l+this.computeTimeTop(a)},getCellDate:function(t){var e=this.view,n=e.calendar;return n.rezoneDate(e.cellToDate(0,t.col).time(this.minTime+this.snapDuration*t.row))},getCellDayEl:function(t){return this.dayEls.eq(t.col)},computeDateTop:function(t,n){return this.computeTimeTop(e.duration(t.clone().stripZone()-n.clone().stripTime()))},computeTimeTop:function(t){var e,n,i,r,s=(t-this.minTime)/this.slotDuration;return s=Math.max(0,s),s=Math.min(this.slatEls.length,s),e=Math.floor(s),n=s-e,i=this.slatTops[e],n?(r=this.slatTops[e+1],i+(r-i)*n):i},computeSlatTops:function(){var e,n=[];this.slatEls.each(function(i,r){e=t(r).position().top,n.push(e)}),n.push(e+this.slatEls.last().outerHeight()),this.slatTops=n},renderDrag:function(t,e,n){var i;return n?(this.renderRangeHelper(t,e,n),i=this.view.opt("dragOpacity"),void 0!==i&&this.helperEl.css("opacity",i),!0):(this.renderHighlight(t,e||this.view.calendar.getDefaultEventEnd(!1,t)),void 0)},destroyDrag:function(){this.destroyHelper(),this.destroyHighlight()},renderResize:function(t,e,n){this.renderRangeHelper(t,e,n)},destroyResize:function(){this.destroyHelper()},renderHelper:function(e,n){var i,r,s,o,l=this.eventsToSegs([e]);for(l=this.renderFgSegEls(l),i=this.renderSegTable(l),r=0;l.length>r;r++)s=l[r],n&&n.col===s.col&&(o=n.el,s.el.css({left:o.css("left"),right:o.css("right"),"margin-left":o.css("margin-left"),"margin-right":o.css("margin-right")}));this.helperEl=t('
').append(i).appendTo(this.el)},destroyHelper:function(){this.helperEl&&(this.helperEl.remove(),this.helperEl=null)},renderSelection:function(t,e){this.view.opt("selectHelper")?this.renderRangeHelper(t,e):this.renderHighlight(t,e)},destroySelection:function(){this.destroyHelper(),this.destroyHighlight()},renderFill:function(e,n,i){var r,s,o,l,a,c,d,u,h,f,g=this.view;if(n.length){for(n=this.renderFillSegEls(e,n),r=this.groupSegCols(n),i=i||e.toLowerCase(),s=t('
'+"
"+"
"),o=s.find("tr"),l=0;r.length>l;l++)if(a=r[l],c=t("").appendTo(o),a.length)for(d=t('
').appendTo(c),u=g.cellToDate(0,l),h=0;a.length>h;h++)f=a[h],d.append(f.el.css({top:this.computeDateTop(f.start,u),bottom:-this.computeDateTop(f.end,u)}));this.bookendCells(o,e),this.el.append(s),this.elsByFill[e]=s}return n}}),t.extend(he.prototype,{eventSkeletonEl:null,renderFgSegs:function(e){return e=this.renderFgSegEls(e),this.el.append(this.eventSkeletonEl=t('
').append(this.renderSegTable(e))),e},destroyFgSegs:function(){this.eventSkeletonEl&&(this.eventSkeletonEl.remove(),this.eventSkeletonEl=null)},renderSegTable:function(e){var n,i,r,s,o,l,a=t("
"),c=a.find("tr");for(n=this.groupSegCols(e),this.computeSegVerticals(e),s=0;n.length>s;s++){for(o=n[s],fe(o),l=t('
'),i=0;o.length>i;i++)r=o[i],r.el.css(this.generateSegPositionCss(r)),30>r.bottom-r.top&&r.el.addClass("fc-short"),l.append(r.el);c.append(t("").append(l))}return this.bookendCells(c,"eventSkeleton"),a +},updateSegVerticals:function(){var t,e=(this.segs||[]).concat(this.businessHourSegs||[]);for(this.computeSegVerticals(e),t=0;e.length>t;t++)e[t].el.css(this.generateSegVerticalCss(e[t]))},computeSegVerticals:function(t){var e,n;for(e=0;t.length>e;e++)n=t[e],n.top=this.computeDateTop(n.start,n.start),n.bottom=this.computeDateTop(n.end,n.start)},fgSegHtml:function(t,e){var n,i,r,s=this.view,o=t.event,l=s.isEventDraggable(o),a=!e&&t.isEnd&&s.isEventResizable(o),c=this.getSegClasses(t,l,a),d=this.getEventSkinCss(o);return c.unshift("fc-time-grid-event"),s.isMultiDayEvent(o)?(t.isStart||t.isEnd)&&(n=s.getEventTimeText(t.start,t.end),i=s.getEventTimeText(t.start,t.end,"LT"),r=s.getEventTimeText(t.start,null)):(n=s.getEventTimeText(o),i=s.getEventTimeText(o,"LT"),r=s.getEventTimeText(o.start,null)),'"+'
'+(n?'
"+""+F(n)+""+"
":"")+(o.title?'
'+F(o.title)+"
":"")+"
"+'
'+(a?'
':"")+""},generateSegPositionCss:function(t){var e,n,i=this.view,r=i.opt("isRTL"),s=i.opt("slotEventOverlap"),o=t.backwardCoord,l=t.forwardCoord,a=this.generateSegVerticalCss(t);return s&&(l=Math.min(1,o+2*(l-o))),r?(e=1-l,n=o):(e=o,n=1-l),a.zIndex=t.level+1,a.left=100*e+"%",a.right=100*n+"%",s&&t.forwardPressure&&(a[r?"marginLeft":"marginRight"]=20),a},generateSegVerticalCss:function(t){return{top:t.top,bottom:-t.bottom}},groupSegCols:function(t){var e,n=this.view,i=[];for(e=0;n.colCnt>e;e++)i.push([]);for(e=0;t.length>e;e++)i[t[e].col].push(t[e]);return i}}),be.prototype={calendar:null,coordMap:null,el:null,start:null,end:null,intervalStart:null,intervalEnd:null,rowCnt:null,colCnt:null,isSelected:!1,scrollerEl:null,scrollTop:null,widgetHeaderClass:null,widgetContentClass:null,highlightStateClass:null,documentMousedownProxy:null,documentDragStartProxy:null,init:function(){var e=this.opt("theme")?"ui":"fc";this.widgetHeaderClass=e+"-widget-header",this.widgetContentClass=e+"-widget-content",this.highlightStateClass=e+"-state-highlight",this.documentMousedownProxy=t.proxy(this,"documentMousedown"),this.documentDragStartProxy=t.proxy(this,"documentDragStart")},render:function(){this.updateSize(),this.trigger("viewRender",this,this,this.el),t(document).on("mousedown",this.documentMousedownProxy).on("dragstart",this.documentDragStartProxy)},destroy:function(){this.unselect(),this.trigger("viewDestroy",this,this,this.el),this.destroyEvents(),this.el.empty(),t(document).off("mousedown",this.documentMousedownProxy).off("dragstart",this.documentDragStartProxy)},incrementDate:function(){},updateSize:function(t){t&&this.recordScroll(),this.updateHeight(),this.updateWidth()},updateWidth:function(){},updateHeight:function(){var t=this.calendar;this.setHeight(t.getSuggestedViewHeight(),t.isHeightAuto())},setHeight:function(){},computeScrollerHeight:function(t){var e,n=this.el.add(this.scrollerEl);return n.css({position:"relative",left:-1}),e=this.el.outerHeight()-this.scrollerEl.height(),n.css({position:"",left:""}),t-e},recordScroll:function(){this.scrollerEl&&(this.scrollTop=this.scrollerEl.scrollTop())},restoreScroll:function(){null!==this.scrollTop&&this.scrollerEl.scrollTop(this.scrollTop)},renderEvents:function(){this.segEach(function(t){this.trigger("eventAfterRender",t.event,t.event,t.el)}),this.trigger("eventAfterAllRender")},destroyEvents:function(){this.segEach(function(t){this.trigger("eventDestroy",t.event,t.event,t.el)})},resolveEventEl:function(e,n){var i=this.trigger("eventRender",e,e,n);return i===!1?n=null:i&&i!==!0&&(n=t(i)),n},showEvent:function(t){this.segEach(function(t){t.el.css("visibility","")},t)},hideEvent:function(t){this.segEach(function(t){t.el.css("visibility","hidden")},t)},segEach:function(t,e){var n,i=this.getSegs();for(n=0;i.length>n;n++)e&&i[n].event._id!==e._id||t.call(this,i[n])},getSegs:function(){},renderDrag:function(){},destroyDrag:function(){},documentDragStart:function(e){var n,i,r,s,o,l=this,a=this.calendar,c=null,d=null,u=null;this.opt("droppable")&&(n=t(e.target),i=this.opt("dropAccept"),(t.isFunction(i)?i.call(n[0],n):n.is(i))&&(r=Ee(n),s=r.eventProps,o=new Q(this.coordMap,{cellOver:function(e,n){c=n,d=r.duration?c.clone().add(r.duration):null,u=d||a.getDefaultEventEnd(!c.hasTime(),c),s&&t.extend(s,{start:c,end:d}),a.isExternalDragAllowedInRange(c,u,s)?l.renderDrag(c,u):(c=null,f())},cellOut:function(){c=null,l.destroyDrag(),g()}}),t(document).one("dragstop",function(t,e){var i;l.destroyDrag(),g(),c&&(r.startTime&&!c.hasTime()&&c.time(r.startTime),l.trigger("drop",n[0],c,t,e),s&&(i=a.renderEvent(s,r.stick),l.trigger("eventReceive",null,i[0])))}),o.startDrag(e)))},select:function(t,e,n){this.unselect(n),this.renderSelection(t,e),this.reportSelection(t,e,n)},renderSelection:function(){},reportSelection:function(t,e,n){this.isSelected=!0,this.trigger("select",null,t,e,n)},unselect:function(t){this.isSelected&&(this.isSelected=!1,this.destroySelection(),this.trigger("unselect",null,t))},destroySelection:function(){},documentMousedown:function(e){var n;this.isSelected&&this.opt("unselectAuto")&&E(e)&&(n=this.opt("unselectCancel"),n&&t(e.target).closest(n).length||this.unselect(e))}},_e.dataAttrPrefix="",De.prototype=M(be.prototype),t.extend(De.prototype,{dayGrid:null,dayNumbersVisible:!1,weekNumbersVisible:!1,weekNumberWidth:null,headRowEl:null,render:function(t,e,n){this.rowCnt=t,this.colCnt=e,this.dayNumbersVisible=n,this.weekNumbersVisible=this.opt("weekNumbers"),this.dayGrid.numbersVisible=this.dayNumbersVisible||this.weekNumbersVisible,this.el.addClass("fc-basic-view").html(this.renderHtml()),this.headRowEl=this.el.find("thead .fc-row"),this.scrollerEl=this.el.find(".fc-day-grid-container"),this.dayGrid.coordMap.containerEl=this.scrollerEl,this.dayGrid.el=this.el.find(".fc-day-grid"),this.dayGrid.render(this.hasRigidRows()),be.prototype.render.call(this)},destroy:function(){this.dayGrid.destroy(),be.prototype.destroy.call(this)},renderHtml:function(){return'"+""+""+""+""+'"+""+""+"
'+this.dayGrid.headHtml()+"
'+'
'+'
'+"
"+"
"},headIntroHtml:function(){return this.weekNumbersVisible?'"+""+F(this.opt("weekNumberTitle"))+""+"":void 0},numberIntroHtml:function(t){return this.weekNumbersVisible?'"+""+this.calendar.calculateWeekNumber(this.cellToDate(t,0))+""+"":void 0},dayIntroHtml:function(){return this.weekNumbersVisible?'":void 0},introHtml:function(){return this.weekNumbersVisible?'":void 0},numberCellHtml:function(t,e,n){var i;return this.dayNumbersVisible?(i=this.dayGrid.getDayClasses(n),i.unshift("fc-day-number"),''+n.date()+""):""},weekNumberStyleAttr:function(){return null!==this.weekNumberWidth?'style="width:'+this.weekNumberWidth+'px"':""},hasRigidRows:function(){var t=this.opt("eventLimit");return t&&"number"!=typeof t},updateWidth:function(){this.weekNumbersVisible&&(this.weekNumberWidth=v(this.el.find(".fc-week-number")))},setHeight:function(t,e){var n,i=this.opt("eventLimit");w(this.scrollerEl),h(this.headRowEl),this.dayGrid.destroySegPopover(),i&&"number"==typeof i&&this.dayGrid.limitRows(i),n=this.computeScrollerHeight(t),this.setGridHeight(n,e),i&&"number"!=typeof i&&this.dayGrid.limitRows(i),!e&&y(this.scrollerEl,n)&&(u(this.headRowEl,b(this.scrollerEl)),n=this.computeScrollerHeight(t),this.scrollerEl.height(n),this.restoreScroll())},setGridHeight:function(t,e){e?m(this.dayGrid.rowEls):p(this.dayGrid.rowEls,t,!0)},renderEvents:function(t){this.dayGrid.renderEvents(t),this.updateHeight(),be.prototype.renderEvents.call(this,t)},getSegs:function(){return this.dayGrid.getSegs()},destroyEvents:function(){be.prototype.destroyEvents.call(this),this.recordScroll(),this.dayGrid.destroyEvents()},renderDrag:function(t,e,n){return this.dayGrid.renderDrag(t,e,n)},destroyDrag:function(){this.dayGrid.destroyDrag()},renderSelection:function(t,e){this.dayGrid.renderSelection(t,e)},destroySelection:function(){this.dayGrid.destroySelection()}}),r({fixedWeekCount:!0}),Ge.month=Te,Te.prototype=M(De.prototype),t.extend(Te.prototype,{name:"month",incrementDate:function(t,e){return t.clone().stripTime().add(e,"months").startOf("month")},render:function(t){var e;this.intervalStart=t.clone().stripTime().startOf("month"),this.intervalEnd=this.intervalStart.clone().add(1,"months"),this.start=this.intervalStart.clone(),this.start=this.skipHiddenDays(this.start),this.start.startOf("week"),this.start=this.skipHiddenDays(this.start),this.end=this.intervalEnd.clone(),this.end=this.skipHiddenDays(this.end,-1,!0),this.end.add((7-this.end.weekday())%7,"days"),this.end=this.skipHiddenDays(this.end,-1,!0),e=Math.ceil(this.end.diff(this.start,"weeks",!0)),this.isFixedWeeks()&&(this.end.add(6-e,"weeks"),e=6),this.title=this.calendar.formatDate(this.intervalStart,this.opt("titleFormat")),De.prototype.render.call(this,e,this.getCellsPerWeek(),!0)},setGridHeight:function(t,e){e=e||"variable"===this.opt("weekMode"),e&&(t*=this.rowCnt/6),p(this.dayGrid.rowEls,t,!e)},isFixedWeeks:function(){var t=this.opt("weekMode");return t?"fixed"===t:this.opt("fixedWeekCount")}}),Ge.basicWeek=Ce,Ce.prototype=M(De.prototype),t.extend(Ce.prototype,{name:"basicWeek",incrementDate:function(t,e){return t.clone().stripTime().add(e,"weeks").startOf("week")},render:function(t){this.intervalStart=t.clone().stripTime().startOf("week"),this.intervalEnd=this.intervalStart.clone().add(1,"weeks"),this.start=this.skipHiddenDays(this.intervalStart),this.end=this.skipHiddenDays(this.intervalEnd,-1,!0),this.title=this.calendar.formatRange(this.start,this.end.clone().subtract(1),this.opt("titleFormat")," — "),De.prototype.render.call(this,1,this.getCellsPerWeek(),!1)}}),Ge.basicDay=He,He.prototype=M(De.prototype),t.extend(He.prototype,{name:"basicDay",incrementDate:function(t,e){var n=t.clone().stripTime().add(e,"days");return n=this.skipHiddenDays(n,0>e?-1:1)},render:function(t){this.start=this.intervalStart=t.clone().stripTime(),this.end=this.intervalEnd=this.start.clone().add(1,"days"),this.title=this.calendar.formatDate(this.start,this.opt("titleFormat")),De.prototype.render.call(this,1,1,!1)}}),r({allDaySlot:!0,allDayText:"all-day",scrollTime:"06:00:00",slotDuration:"00:30:00",axisFormat:xe,timeFormat:{agenda:ke},minTime:"00:00:00",maxTime:"24:00:00",slotEventOverlap:!0});var Ue=5;Me.prototype=M(be.prototype),t.extend(Me.prototype,{timeGrid:null,dayGrid:null,axisWidth:null,noScrollRowEls:null,bottomRuleEl:null,bottomRuleHeight:null,render:function(e){this.rowCnt=1,this.colCnt=e,this.el.addClass("fc-agenda-view").html(this.renderHtml()),this.scrollerEl=this.el.find(".fc-time-grid-container"),this.timeGrid.coordMap.containerEl=this.scrollerEl,this.timeGrid.el=this.el.find(".fc-time-grid"),this.timeGrid.render(),this.bottomRuleEl=t('
').appendTo(this.timeGrid.el),this.dayGrid&&(this.dayGrid.el=this.el.find(".fc-day-grid"),this.dayGrid.render(),this.dayGrid.bottomCoordPadding=this.dayGrid.el.next("hr").outerHeight()),this.noScrollRowEls=this.el.find(".fc-row:not(.fc-scroller *)"),be.prototype.render.call(this),this.resetScroll()},destroy:function(){this.timeGrid.destroy(),this.dayGrid&&this.dayGrid.destroy(),be.prototype.destroy.call(this)},renderHtml:function(){return'"+""+""+""+""+'"+""+""+"
'+this.timeGrid.headHtml()+"
'+(this.dayGrid?'

':"")+'
'+'
'+"
"+"
"},headIntroHtml:function(){var t,e,n,i;return this.opt("weekNumbers")?(t=this.cellToDate(0,0),e=this.calendar.calculateWeekNumber(t),n=this.opt("weekNumberTitle"),i=this.opt("isRTL")?e+n:n+e,'"+""+F(i)+""+""):'"},dayIntroHtml:function(){return'"+""+(this.opt("allDayHtml")||F(this.opt("allDayText")))+""+""},slotBgIntroHtml:function(){return'"},introHtml:function(){return'"},axisStyleAttr:function(){return null!==this.axisWidth?'style="width:'+this.axisWidth+'px"':""},updateSize:function(t){t&&this.timeGrid.resize(),be.prototype.updateSize.call(this,t)},updateWidth:function(){this.axisWidth=v(this.el.find(".fc-axis"))},setHeight:function(t,e){var n,i;null===this.bottomRuleHeight&&(this.bottomRuleHeight=this.bottomRuleEl.outerHeight()),this.bottomRuleEl.hide(),this.scrollerEl.css("overflow",""),w(this.scrollerEl),h(this.noScrollRowEls),this.dayGrid&&(this.dayGrid.destroySegPopover(),n=this.opt("eventLimit"),n&&"number"!=typeof n&&(n=Ue),n&&this.dayGrid.limitRows(n)),e||(i=this.computeScrollerHeight(t),y(this.scrollerEl,i)?(u(this.noScrollRowEls,b(this.scrollerEl)),i=this.computeScrollerHeight(t),this.scrollerEl.height(i),this.restoreScroll()):(this.scrollerEl.height(i).css("overflow","hidden"),this.bottomRuleEl.show()))},resetScroll:function(){function t(){n.scrollerEl.scrollTop(r)}var n=this,i=e.duration(this.opt("scrollTime")),r=this.timeGrid.computeTimeTop(i);r=Math.ceil(r),r&&r++,t(),setTimeout(t,0)},renderEvents:function(t){var e,n,i=[],r=[],s=[];for(n=0;t.length>n;n++)t[n].allDay?i.push(t[n]):r.push(t[n]);e=this.timeGrid.renderEvents(r),this.dayGrid&&(s=this.dayGrid.renderEvents(i)),this.updateHeight(),be.prototype.renderEvents.call(this,t)},getSegs:function(){return this.timeGrid.getSegs().concat(this.dayGrid?this.dayGrid.getSegs():[])},destroyEvents:function(){be.prototype.destroyEvents.call(this),this.recordScroll(),this.timeGrid.destroyEvents(),this.dayGrid&&this.dayGrid.destroyEvents()},renderDrag:function(t,e,n){return t.hasTime()?this.timeGrid.renderDrag(t,e,n):this.dayGrid?this.dayGrid.renderDrag(t,e,n):void 0},destroyDrag:function(){this.timeGrid.destroyDrag(),this.dayGrid&&this.dayGrid.destroyDrag()},renderSelection:function(t,e){t.hasTime()||e.hasTime()?this.timeGrid.renderSelection(t,e):this.dayGrid&&this.dayGrid.renderSelection(t,e)},destroySelection:function(){this.timeGrid.destroySelection(),this.dayGrid&&this.dayGrid.destroySelection()}}),Ge.agendaWeek=Re,Re.prototype=M(Me.prototype),t.extend(Re.prototype,{name:"agendaWeek",incrementDate:function(t,e){return t.clone().stripTime().add(e,"weeks").startOf("week")},render:function(t){this.intervalStart=t.clone().stripTime().startOf("week"),this.intervalEnd=this.intervalStart.clone().add(1,"weeks"),this.start=this.skipHiddenDays(this.intervalStart),this.end=this.skipHiddenDays(this.intervalEnd,-1,!0),this.title=this.calendar.formatRange(this.start,this.end.clone().subtract(1),this.opt("titleFormat")," — "),Me.prototype.render.call(this,this.getCellsPerWeek())}}),Ge.agendaDay=Pe,Pe.prototype=M(Me.prototype),t.extend(Pe.prototype,{name:"agendaDay",incrementDate:function(t,e){var n=t.clone().stripTime().add(e,"days");return n=this.skipHiddenDays(n,0>e?-1:1)},render:function(t){this.start=this.intervalStart=t.clone().stripTime(),this.end=this.intervalEnd=this.start.clone().add(1,"days"),this.title=this.calendar.formatDate(this.start,this.opt("titleFormat")),Me.prototype.render.call(this,1)}})}); \ No newline at end of file diff --git a/static/js/plugins/fullcalendar/moment.min.js b/static/js/plugins/fullcalendar/moment.min.js new file mode 100644 index 000000000000..8b54f130f3a1 --- /dev/null +++ b/static/js/plugins/fullcalendar/moment.min.js @@ -0,0 +1,7 @@ +//! moment.js +//! version : 2.8.3 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com +(function(a){function b(a,b,c){switch(arguments.length){case 2:return null!=a?a:b;case 3:return null!=a?a:null!=b?b:c;default:throw new Error("Implement me")}}function c(a,b){return zb.call(a,b)}function d(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function e(a){tb.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+a)}function f(a,b){var c=!0;return m(function(){return c&&(e(a),c=!1),b.apply(this,arguments)},b)}function g(a,b){qc[a]||(e(b),qc[a]=!0)}function h(a,b){return function(c){return p(a.call(this,c),b)}}function i(a,b){return function(c){return this.localeData().ordinal(a.call(this,c),b)}}function j(){}function k(a,b){b!==!1&&F(a),n(this,a),this._d=new Date(+a._d)}function l(a){var b=y(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;this._milliseconds=+k+1e3*j+6e4*i+36e5*h,this._days=+g+7*f,this._months=+e+3*d+12*c,this._data={},this._locale=tb.localeData(),this._bubble()}function m(a,b){for(var d in b)c(b,d)&&(a[d]=b[d]);return c(b,"toString")&&(a.toString=b.toString),c(b,"valueOf")&&(a.valueOf=b.valueOf),a}function n(a,b){var c,d,e;if("undefined"!=typeof b._isAMomentObject&&(a._isAMomentObject=b._isAMomentObject),"undefined"!=typeof b._i&&(a._i=b._i),"undefined"!=typeof b._f&&(a._f=b._f),"undefined"!=typeof b._l&&(a._l=b._l),"undefined"!=typeof b._strict&&(a._strict=b._strict),"undefined"!=typeof b._tzm&&(a._tzm=b._tzm),"undefined"!=typeof b._isUTC&&(a._isUTC=b._isUTC),"undefined"!=typeof b._offset&&(a._offset=b._offset),"undefined"!=typeof b._pf&&(a._pf=b._pf),"undefined"!=typeof b._locale&&(a._locale=b._locale),Ib.length>0)for(c in Ib)d=Ib[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function o(a){return 0>a?Math.ceil(a):Math.floor(a)}function p(a,b,c){for(var d=""+Math.abs(a),e=a>=0;d.lengthd;d++)(c&&a[d]!==b[d]||!c&&A(a[d])!==A(b[d]))&&g++;return g+f}function x(a){if(a){var b=a.toLowerCase().replace(/(.)s$/,"$1");a=jc[a]||kc[b]||b}return a}function y(a){var b,d,e={};for(d in a)c(a,d)&&(b=x(d),b&&(e[b]=a[d]));return e}function z(b){var c,d;if(0===b.indexOf("week"))c=7,d="day";else{if(0!==b.indexOf("month"))return;c=12,d="month"}tb[b]=function(e,f){var g,h,i=tb._locale[b],j=[];if("number"==typeof e&&(f=e,e=a),h=function(a){var b=tb().utc().set(d,a);return i.call(tb._locale,b,e||"")},null!=f)return h(f);for(g=0;c>g;g++)j.push(h(g));return j}}function A(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function B(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function C(a,b,c){return hb(tb([a,11,31+b-c]),b,c).week}function D(a){return E(a)?366:365}function E(a){return a%4===0&&a%100!==0||a%400===0}function F(a){var b;a._a&&-2===a._pf.overflow&&(b=a._a[Bb]<0||a._a[Bb]>11?Bb:a._a[Cb]<1||a._a[Cb]>B(a._a[Ab],a._a[Bb])?Cb:a._a[Db]<0||a._a[Db]>23?Db:a._a[Eb]<0||a._a[Eb]>59?Eb:a._a[Fb]<0||a._a[Fb]>59?Fb:a._a[Gb]<0||a._a[Gb]>999?Gb:-1,a._pf._overflowDayOfYear&&(Ab>b||b>Cb)&&(b=Cb),a._pf.overflow=b)}function G(a){return null==a._isValid&&(a._isValid=!isNaN(a._d.getTime())&&a._pf.overflow<0&&!a._pf.empty&&!a._pf.invalidMonth&&!a._pf.nullInput&&!a._pf.invalidFormat&&!a._pf.userInvalidated,a._strict&&(a._isValid=a._isValid&&0===a._pf.charsLeftOver&&0===a._pf.unusedTokens.length)),a._isValid}function H(a){return a?a.toLowerCase().replace("_","-"):a}function I(a){for(var b,c,d,e,f=0;f0;){if(d=J(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&w(e,c,!0)>=b-1)break;b--}f++}return null}function J(a){var b=null;if(!Hb[a]&&Jb)try{b=tb.locale(),require("./locale/"+a),tb.locale(b)}catch(c){}return Hb[a]}function K(a,b){return b._isUTC?tb(a).zone(b._offset||0):tb(a).local()}function L(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function M(a){var b,c,d=a.match(Nb);for(b=0,c=d.length;c>b;b++)d[b]=pc[d[b]]?pc[d[b]]:L(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function N(a,b){return a.isValid()?(b=O(b,a.localeData()),lc[b]||(lc[b]=M(b)),lc[b](a)):a.localeData().invalidDate()}function O(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Ob.lastIndex=0;d>=0&&Ob.test(a);)a=a.replace(Ob,c),Ob.lastIndex=0,d-=1;return a}function P(a,b){var c,d=b._strict;switch(a){case"Q":return Zb;case"DDDD":return _b;case"YYYY":case"GGGG":case"gggg":return d?ac:Rb;case"Y":case"G":case"g":return cc;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return d?bc:Sb;case"S":if(d)return Zb;case"SS":if(d)return $b;case"SSS":if(d)return _b;case"DDD":return Qb;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Ub;case"a":case"A":return b._locale._meridiemParse;case"X":return Xb;case"Z":case"ZZ":return Vb;case"T":return Wb;case"SSSS":return Tb;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return d?$b:Pb;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return Pb;case"Do":return Yb;default:return c=new RegExp(Y(X(a.replace("\\","")),"i"))}}function Q(a){a=a||"";var b=a.match(Vb)||[],c=b[b.length-1]||[],d=(c+"").match(hc)||["-",0,0],e=+(60*d[1])+A(d[2]);return"+"===d[0]?-e:e}function R(a,b,c){var d,e=c._a;switch(a){case"Q":null!=b&&(e[Bb]=3*(A(b)-1));break;case"M":case"MM":null!=b&&(e[Bb]=A(b)-1);break;case"MMM":case"MMMM":d=c._locale.monthsParse(b),null!=d?e[Bb]=d:c._pf.invalidMonth=b;break;case"D":case"DD":null!=b&&(e[Cb]=A(b));break;case"Do":null!=b&&(e[Cb]=A(parseInt(b,10)));break;case"DDD":case"DDDD":null!=b&&(c._dayOfYear=A(b));break;case"YY":e[Ab]=tb.parseTwoDigitYear(b);break;case"YYYY":case"YYYYY":case"YYYYYY":e[Ab]=A(b);break;case"a":case"A":c._isPm=c._locale.isPM(b);break;case"H":case"HH":case"h":case"hh":e[Db]=A(b);break;case"m":case"mm":e[Eb]=A(b);break;case"s":case"ss":e[Fb]=A(b);break;case"S":case"SS":case"SSS":case"SSSS":e[Gb]=A(1e3*("0."+b));break;case"X":c._d=new Date(1e3*parseFloat(b));break;case"Z":case"ZZ":c._useUTC=!0,c._tzm=Q(b);break;case"dd":case"ddd":case"dddd":d=c._locale.weekdaysParse(b),null!=d?(c._w=c._w||{},c._w.d=d):c._pf.invalidWeekday=b;break;case"w":case"ww":case"W":case"WW":case"d":case"e":case"E":a=a.substr(0,1);case"gggg":case"GGGG":case"GGGGG":a=a.substr(0,2),b&&(c._w=c._w||{},c._w[a]=A(b));break;case"gg":case"GG":c._w=c._w||{},c._w[a]=tb.parseTwoDigitYear(b)}}function S(a){var c,d,e,f,g,h,i;c=a._w,null!=c.GG||null!=c.W||null!=c.E?(g=1,h=4,d=b(c.GG,a._a[Ab],hb(tb(),1,4).year),e=b(c.W,1),f=b(c.E,1)):(g=a._locale._week.dow,h=a._locale._week.doy,d=b(c.gg,a._a[Ab],hb(tb(),g,h).year),e=b(c.w,1),null!=c.d?(f=c.d,g>f&&++e):f=null!=c.e?c.e+g:g),i=ib(d,e,f,h,g),a._a[Ab]=i.year,a._dayOfYear=i.dayOfYear}function T(a){var c,d,e,f,g=[];if(!a._d){for(e=V(a),a._w&&null==a._a[Cb]&&null==a._a[Bb]&&S(a),a._dayOfYear&&(f=b(a._a[Ab],e[Ab]),a._dayOfYear>D(f)&&(a._pf._overflowDayOfYear=!0),d=db(f,0,a._dayOfYear),a._a[Bb]=d.getUTCMonth(),a._a[Cb]=d.getUTCDate()),c=0;3>c&&null==a._a[c];++c)a._a[c]=g[c]=e[c];for(;7>c;c++)a._a[c]=g[c]=null==a._a[c]?2===c?1:0:a._a[c];a._d=(a._useUTC?db:cb).apply(null,g),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()+a._tzm)}}function U(a){var b;a._d||(b=y(a._i),a._a=[b.year,b.month,b.day,b.hour,b.minute,b.second,b.millisecond],T(a))}function V(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function W(a){if(a._f===tb.ISO_8601)return void $(a);a._a=[],a._pf.empty=!0;var b,c,d,e,f,g=""+a._i,h=g.length,i=0;for(d=O(a._f,a._locale).match(Nb)||[],b=0;b0&&a._pf.unusedInput.push(f),g=g.slice(g.indexOf(c)+c.length),i+=c.length),pc[e]?(c?a._pf.empty=!1:a._pf.unusedTokens.push(e),R(e,c,a)):a._strict&&!c&&a._pf.unusedTokens.push(e);a._pf.charsLeftOver=h-i,g.length>0&&a._pf.unusedInput.push(g),a._isPm&&a._a[Db]<12&&(a._a[Db]+=12),a._isPm===!1&&12===a._a[Db]&&(a._a[Db]=0),T(a),F(a)}function X(a){return a.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e})}function Y(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function Z(a){var b,c,e,f,g;if(0===a._f.length)return a._pf.invalidFormat=!0,void(a._d=new Date(0/0));for(f=0;fg)&&(e=g,c=b));m(a,c||b)}function $(a){var b,c,d=a._i,e=dc.exec(d);if(e){for(a._pf.iso=!0,b=0,c=fc.length;c>b;b++)if(fc[b][1].exec(d)){a._f=fc[b][0]+(e[6]||" ");break}for(b=0,c=gc.length;c>b;b++)if(gc[b][1].exec(d)){a._f+=gc[b][0];break}d.match(Vb)&&(a._f+="Z"),W(a)}else a._isValid=!1}function _(a){$(a),a._isValid===!1&&(delete a._isValid,tb.createFromInputFallback(a))}function ab(a,b){var c,d=[];for(c=0;ca&&h.setFullYear(a),h}function db(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function eb(a,b){if("string"==typeof a)if(isNaN(a)){if(a=b.weekdaysParse(a),"number"!=typeof a)return null}else a=parseInt(a,10);return a}function fb(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function gb(a,b,c){var d=tb.duration(a).abs(),e=yb(d.as("s")),f=yb(d.as("m")),g=yb(d.as("h")),h=yb(d.as("d")),i=yb(d.as("M")),j=yb(d.as("y")),k=e0,k[4]=c,fb.apply({},k)}function hb(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=tb(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function ib(a,b,c,d,e){var f,g,h=db(a,0,1).getUTCDay();return h=0===h?7:h,c=null!=c?c:e,f=e-h+(h>d?7:0)-(e>h?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:D(a-1)+g}}function jb(b){var c=b._i,d=b._f;return b._locale=b._locale||tb.localeData(b._l),null===c||d===a&&""===c?tb.invalid({nullInput:!0}):("string"==typeof c&&(b._i=c=b._locale.preparse(c)),tb.isMoment(c)?new k(c,!0):(d?u(d)?Z(b):W(b):bb(b),new k(b)))}function kb(a,b){var c,d;if(1===b.length&&u(b[0])&&(b=b[0]),!b.length)return tb();for(c=b[0],d=1;d=0?"+":"-";return b+p(Math.abs(a),6)},gg:function(){return p(this.weekYear()%100,2)},gggg:function(){return p(this.weekYear(),4)},ggggg:function(){return p(this.weekYear(),5)},GG:function(){return p(this.isoWeekYear()%100,2)},GGGG:function(){return p(this.isoWeekYear(),4)},GGGGG:function(){return p(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.localeData().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.localeData().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return A(this.milliseconds()/100)},SS:function(){return p(A(this.milliseconds()/10),2)},SSS:function(){return p(this.milliseconds(),3)},SSSS:function(){return p(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+p(A(a/60),2)+":"+p(A(a)%60,2)},ZZ:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+p(A(a/60),2)+p(A(a)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()},Q:function(){return this.quarter()}},qc={},rc=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"];nc.length;)vb=nc.pop(),pc[vb+"o"]=i(pc[vb],vb);for(;oc.length;)vb=oc.pop(),pc[vb+vb]=h(pc[vb],2);pc.DDDD=h(pc.DDD,3),m(j.prototype,{set:function(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(a){return this._months[a.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(a){return this._monthsShort[a.month()]},monthsParse:function(a){var b,c,d;for(this._monthsParse||(this._monthsParse=[]),b=0;12>b;b++)if(this._monthsParse[b]||(c=tb.utc([2e3,b]),d="^"+this.months(c,"")+"|^"+this.monthsShort(c,""),this._monthsParse[b]=new RegExp(d.replace(".",""),"i")),this._monthsParse[b].test(a))return b},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(a){return this._weekdays[a.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(a){return this._weekdaysShort[a.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(a){return this._weekdaysMin[a.day()]},weekdaysParse:function(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=tb([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY LT",LLLL:"dddd, MMMM D, YYYY LT"},longDateFormat:function(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b},isPM:function(a){return"p"===(a+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(a,b){var c=this._calendar[a];return"function"==typeof c?c.apply(b):c},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)},pastFuture:function(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)},ordinal:function(a){return this._ordinal.replace("%d",a)},_ordinal:"%d",preparse:function(a){return a},postformat:function(a){return a},week:function(a){return hb(a,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),tb=function(b,c,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._i=b,g._f=c,g._l=e,g._strict=f,g._isUTC=!1,g._pf=d(),jb(g)},tb.suppressDeprecationWarnings=!1,tb.createFromInputFallback=f("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i)}),tb.min=function(){var a=[].slice.call(arguments,0);return kb("isBefore",a)},tb.max=function(){var a=[].slice.call(arguments,0);return kb("isAfter",a)},tb.utc=function(b,c,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._useUTC=!0,g._isUTC=!0,g._l=e,g._i=b,g._f=c,g._strict=f,g._pf=d(),jb(g).utc()},tb.unix=function(a){return tb(1e3*a)},tb.duration=function(a,b){var d,e,f,g,h=a,i=null;return tb.isDuration(a)?h={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(h={},b?h[b]=a:h.milliseconds=a):(i=Lb.exec(a))?(d="-"===i[1]?-1:1,h={y:0,d:A(i[Cb])*d,h:A(i[Db])*d,m:A(i[Eb])*d,s:A(i[Fb])*d,ms:A(i[Gb])*d}):(i=Mb.exec(a))?(d="-"===i[1]?-1:1,f=function(a){var b=a&&parseFloat(a.replace(",","."));return(isNaN(b)?0:b)*d},h={y:f(i[2]),M:f(i[3]),d:f(i[4]),h:f(i[5]),m:f(i[6]),s:f(i[7]),w:f(i[8])}):"object"==typeof h&&("from"in h||"to"in h)&&(g=r(tb(h.from),tb(h.to)),h={},h.ms=g.milliseconds,h.M=g.months),e=new l(h),tb.isDuration(a)&&c(a,"_locale")&&(e._locale=a._locale),e},tb.version=wb,tb.defaultFormat=ec,tb.ISO_8601=function(){},tb.momentProperties=Ib,tb.updateOffset=function(){},tb.relativeTimeThreshold=function(b,c){return mc[b]===a?!1:c===a?mc[b]:(mc[b]=c,!0)},tb.lang=f("moment.lang is deprecated. Use moment.locale instead.",function(a,b){return tb.locale(a,b)}),tb.locale=function(a,b){var c;return a&&(c="undefined"!=typeof b?tb.defineLocale(a,b):tb.localeData(a),c&&(tb.duration._locale=tb._locale=c)),tb._locale._abbr},tb.defineLocale=function(a,b){return null!==b?(b.abbr=a,Hb[a]||(Hb[a]=new j),Hb[a].set(b),tb.locale(a),Hb[a]):(delete Hb[a],null)},tb.langData=f("moment.langData is deprecated. Use moment.localeData instead.",function(a){return tb.localeData(a)}),tb.localeData=function(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return tb._locale;if(!u(a)){if(b=J(a))return b;a=[a]}return I(a)},tb.isMoment=function(a){return a instanceof k||null!=a&&c(a,"_isAMomentObject")},tb.isDuration=function(a){return a instanceof l};for(vb=rc.length-1;vb>=0;--vb)z(rc[vb]);tb.normalizeUnits=function(a){return x(a)},tb.invalid=function(a){var b=tb.utc(0/0);return null!=a?m(b._pf,a):b._pf.userInvalidated=!0,b},tb.parseZone=function(){return tb.apply(null,arguments).parseZone()},tb.parseTwoDigitYear=function(a){return A(a)+(A(a)>68?1900:2e3)},m(tb.fn=k.prototype,{clone:function(){return tb(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){var a=tb(this).utc();return 00:!1},parsingFlags:function(){return m({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(a){return this.zone(0,a)},local:function(a){return this._isUTC&&(this.zone(0,a),this._isUTC=!1,a&&this.add(this._dateTzOffset(),"m")),this},format:function(a){var b=N(this,a||tb.defaultFormat);return this.localeData().postformat(b)},add:s(1,"add"),subtract:s(-1,"subtract"),diff:function(a,b,c){var d,e,f,g=K(a,this),h=6e4*(this.zone()-g.zone());return b=x(b),"year"===b||"month"===b?(d=432e5*(this.daysInMonth()+g.daysInMonth()),e=12*(this.year()-g.year())+(this.month()-g.month()),f=this-tb(this).startOf("month")-(g-tb(g).startOf("month")),f-=6e4*(this.zone()-tb(this).startOf("month").zone()-(g.zone()-tb(g).startOf("month").zone())),e+=f/d,"year"===b&&(e/=12)):(d=this-g,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-h)/864e5:"week"===b?(d-h)/6048e5:d),c?e:o(e)},from:function(a,b){return tb.duration({to:this,from:a}).locale(this.locale()).humanize(!b)},fromNow:function(a){return this.from(tb(),a)},calendar:function(a){var b=a||tb(),c=K(b,this).startOf("day"),d=this.diff(c,"days",!0),e=-6>d?"sameElse":-1>d?"lastWeek":0>d?"lastDay":1>d?"sameDay":2>d?"nextDay":7>d?"nextWeek":"sameElse";return this.format(this.localeData().calendar(e,this))},isLeapYear:function(){return E(this.year())},isDST:function(){return this.zone()+a):+this.clone().startOf(b)>+tb(a).startOf(b)},isBefore:function(a,b){return b=x("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=tb.isMoment(a)?a:tb(a),+a>+this):+this.clone().startOf(b)<+tb(a).startOf(b)},isSame:function(a,b){return b=x(b||"millisecond"),"millisecond"===b?(a=tb.isMoment(a)?a:tb(a),+this===+a):+this.clone().startOf(b)===+K(a,this).startOf(b)},min:f("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(a){return a=tb.apply(null,arguments),this>a?this:a}),max:f("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(a){return a=tb.apply(null,arguments),a>this?this:a}),zone:function(a,b){var c,d=this._offset||0;return null==a?this._isUTC?d:this._dateTzOffset():("string"==typeof a&&(a=Q(a)),Math.abs(a)<16&&(a=60*a),!this._isUTC&&b&&(c=this._dateTzOffset()),this._offset=a,this._isUTC=!0,null!=c&&this.subtract(c,"m"),d!==a&&(!b||this._changeInProgress?t(this,tb.duration(d-a,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,tb.updateOffset(this,!0),this._changeInProgress=null)),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.zone(this._tzm):"string"==typeof this._i&&this.zone(this._i),this},hasAlignedHourOffset:function(a){return a=a?tb(a).zone():0,(this.zone()-a)%60===0},daysInMonth:function(){return B(this.year(),this.month())},dayOfYear:function(a){var b=yb((tb(this).startOf("day")-tb(this).startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")},quarter:function(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)},weekYear:function(a){var b=hb(this,this.localeData()._week.dow,this.localeData()._week.doy).year;return null==a?b:this.add(a-b,"y")},isoWeekYear:function(a){var b=hb(this,1,4).year;return null==a?b:this.add(a-b,"y")},week:function(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")},isoWeek:function(a){var b=hb(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")},weekday:function(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")},isoWeekday:function(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)},isoWeeksInYear:function(){return C(this.year(),1,4)},weeksInYear:function(){var a=this.localeData()._week;return C(this.year(),a.dow,a.doy)},get:function(a){return a=x(a),this[a]()},set:function(a,b){return a=x(a),"function"==typeof this[a]&&this[a](b),this},locale:function(b){var c;return b===a?this._locale._abbr:(c=tb.localeData(b),null!=c&&(this._locale=c),this)},lang:f("moment().lang() is deprecated. Use moment().localeData() instead.",function(b){return b===a?this.localeData():this.locale(b)}),localeData:function(){return this._locale},_dateTzOffset:function(){return 15*Math.round(this._d.getTimezoneOffset()/15)}}),tb.fn.millisecond=tb.fn.milliseconds=ob("Milliseconds",!1),tb.fn.second=tb.fn.seconds=ob("Seconds",!1),tb.fn.minute=tb.fn.minutes=ob("Minutes",!1),tb.fn.hour=tb.fn.hours=ob("Hours",!0),tb.fn.date=ob("Date",!0),tb.fn.dates=f("dates accessor is deprecated. Use date instead.",ob("Date",!0)),tb.fn.year=ob("FullYear",!0),tb.fn.years=f("years accessor is deprecated. Use year instead.",ob("FullYear",!0)),tb.fn.days=tb.fn.day,tb.fn.months=tb.fn.month,tb.fn.weeks=tb.fn.week,tb.fn.isoWeeks=tb.fn.isoWeek,tb.fn.quarters=tb.fn.quarter,tb.fn.toJSON=tb.fn.toISOString,m(tb.duration.fn=l.prototype,{_bubble:function(){var a,b,c,d=this._milliseconds,e=this._days,f=this._months,g=this._data,h=0;g.milliseconds=d%1e3,a=o(d/1e3),g.seconds=a%60,b=o(a/60),g.minutes=b%60,c=o(b/60),g.hours=c%24,e+=o(c/24),h=o(pb(e)),e-=o(qb(h)),f+=o(e/30),e%=30,h+=o(f/12),f%=12,g.days=e,g.months=f,g.years=h},abs:function(){return this._milliseconds=Math.abs(this._milliseconds),this._days=Math.abs(this._days),this._months=Math.abs(this._months),this._data.milliseconds=Math.abs(this._data.milliseconds),this._data.seconds=Math.abs(this._data.seconds),this._data.minutes=Math.abs(this._data.minutes),this._data.hours=Math.abs(this._data.hours),this._data.months=Math.abs(this._data.months),this._data.years=Math.abs(this._data.years),this},weeks:function(){return o(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*A(this._months/12)},humanize:function(a){var b=gb(this,!a,this.localeData());return a&&(b=this.localeData().pastFuture(+this,b)),this.localeData().postformat(b)},add:function(a,b){var c=tb.duration(a,b);return this._milliseconds+=c._milliseconds,this._days+=c._days,this._months+=c._months,this._bubble(),this},subtract:function(a,b){var c=tb.duration(a,b);return this._milliseconds-=c._milliseconds,this._days-=c._days,this._months-=c._months,this._bubble(),this},get:function(a){return a=x(a),this[a.toLowerCase()+"s"]()},as:function(a){var b,c;if(a=x(a),"month"===a||"year"===a)return b=this._days+this._milliseconds/864e5,c=this._months+12*pb(b),"month"===a?c:c/12;switch(b=this._days+qb(this._months/12),a){case"week":return b/7+this._milliseconds/6048e5;case"day":return b+this._milliseconds/864e5;case"hour":return 24*b+this._milliseconds/36e5;case"minute":return 24*b*60+this._milliseconds/6e4;case"second":return 24*b*60*60+this._milliseconds/1e3;case"millisecond":return Math.floor(24*b*60*60*1e3)+this._milliseconds;default:throw new Error("Unknown unit "+a)}},lang:tb.fn.lang,locale:tb.fn.locale,toIsoString:f("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",function(){return this.toISOString()}),toISOString:function(){var a=Math.abs(this.years()),b=Math.abs(this.months()),c=Math.abs(this.days()),d=Math.abs(this.hours()),e=Math.abs(this.minutes()),f=Math.abs(this.seconds()+this.milliseconds()/1e3);return this.asSeconds()?(this.asSeconds()<0?"-":"")+"P"+(a?a+"Y":"")+(b?b+"M":"")+(c?c+"D":"")+(d||e||f?"T":"")+(d?d+"H":"")+(e?e+"M":"")+(f?f+"S":""):"P0D"},localeData:function(){return this._locale}}),tb.duration.fn.toString=tb.duration.fn.toISOString;for(vb in ic)c(ic,vb)&&rb(vb.toLowerCase());tb.duration.fn.asMilliseconds=function(){return this.as("ms")},tb.duration.fn.asSeconds=function(){return this.as("s")},tb.duration.fn.asMinutes=function(){return this.as("m")},tb.duration.fn.asHours=function(){return this.as("h")},tb.duration.fn.asDays=function(){return this.as("d")},tb.duration.fn.asWeeks=function(){return this.as("weeks")},tb.duration.fn.asMonths=function(){return this.as("M")},tb.duration.fn.asYears=function(){return this.as("y")},tb.locale("en",{ordinal:function(a){var b=a%10,c=1===A(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th"; +return a+c}}),Jb?module.exports=tb:"function"==typeof define&&define.amd?(define("moment",function(a,b,c){return c.config&&c.config()&&c.config().noGlobal===!0&&(xb.moment=ub),tb}),sb(!0)):sb()}).call(this); \ No newline at end of file diff --git a/static/js/plugins/iCheck/icheck.min.js b/static/js/plugins/iCheck/icheck.min.js new file mode 100644 index 000000000000..9b826fb7e6c5 --- /dev/null +++ b/static/js/plugins/iCheck/icheck.min.js @@ -0,0 +1,11 @@ +/*! iCheck v1.0.2 by Damir Sultanov, http://git.io/arlzeA, MIT Licensed */ +(function(f){function A(a,b,d){var c=a[0],g=/er/.test(d)?_indeterminate:/bl/.test(d)?n:k,e=d==_update?{checked:c[k],disabled:c[n],indeterminate:"true"==a.attr(_indeterminate)||"false"==a.attr(_determinate)}:c[g];if(/^(ch|di|in)/.test(d)&&!e)x(a,g);else if(/^(un|en|de)/.test(d)&&e)q(a,g);else if(d==_update)for(var f in e)e[f]?x(a,f,!0):q(a,f,!0);else if(!b||"toggle"==d){if(!b)a[_callback]("ifClicked");e?c[_type]!==r&&q(a,g):x(a,g)}}function x(a,b,d){var c=a[0],g=a.parent(),e=b==k,u=b==_indeterminate, + v=b==n,s=u?_determinate:e?y:"enabled",F=l(a,s+t(c[_type])),B=l(a,b+t(c[_type]));if(!0!==c[b]){if(!d&&b==k&&c[_type]==r&&c.name){var w=a.closest("form"),p='input[name="'+c.name+'"]',p=w.length?w.find(p):f(p);p.each(function(){this!==c&&f(this).data(m)&&q(f(this),b)})}u?(c[b]=!0,c[k]&&q(a,k,"force")):(d||(c[b]=!0),e&&c[_indeterminate]&&q(a,_indeterminate,!1));D(a,e,b,d)}c[n]&&l(a,_cursor,!0)&&g.find("."+C).css(_cursor,"default");g[_add](B||l(a,b)||"");g.attr("role")&&!u&&g.attr("aria-"+(v?n:k),"true"); + g[_remove](F||l(a,s)||"")}function q(a,b,d){var c=a[0],g=a.parent(),e=b==k,f=b==_indeterminate,m=b==n,s=f?_determinate:e?y:"enabled",q=l(a,s+t(c[_type])),r=l(a,b+t(c[_type]));if(!1!==c[b]){if(f||!d||"force"==d)c[b]=!1;D(a,e,s,d)}!c[n]&&l(a,_cursor,!0)&&g.find("."+C).css(_cursor,"pointer");g[_remove](r||l(a,b)||"");g.attr("role")&&!f&&g.attr("aria-"+(m?n:k),"false");g[_add](q||l(a,s)||"")}function E(a,b){if(a.data(m)){a.parent().html(a.attr("style",a.data(m).s||""));if(b)a[_callback](b);a.off(".i").unwrap(); + f(_label+'[for="'+a[0].id+'"]').add(a.closest(_label)).off(".i")}}function l(a,b,f){if(a.data(m))return a.data(m).o[b+(f?"":"Class")]}function t(a){return a.charAt(0).toUpperCase()+a.slice(1)}function D(a,b,f,c){if(!c){if(b)a[_callback]("ifToggled");a[_callback]("ifChanged")[_callback]("if"+t(f))}}var m="iCheck",C=m+"-helper",r="radio",k="checked",y="un"+k,n="disabled";_determinate="determinate";_indeterminate="in"+_determinate;_update="update";_type="type";_click="click";_touch="touchbegin.i touchend.i"; + _add="addClass";_remove="removeClass";_callback="trigger";_label="label";_cursor="cursor";_mobile=/ipad|iphone|ipod|android|blackberry|windows phone|opera mini|silk/i.test(navigator.userAgent);f.fn[m]=function(a,b){var d='input[type="checkbox"], input[type="'+r+'"]',c=f(),g=function(a){a.each(function(){var a=f(this);c=a.is(d)?c.add(a):c.add(a.find(d))})};if(/^(check|uncheck|toggle|indeterminate|determinate|disable|enable|update|destroy)$/i.test(a))return a=a.toLowerCase(),g(this),c.each(function(){var c= + f(this);"destroy"==a?E(c,"ifDestroyed"):A(c,!0,a);f.isFunction(b)&&b()});if("object"!=typeof a&&a)return this;var e=f.extend({checkedClass:k,disabledClass:n,indeterminateClass:_indeterminate,labelHover:!0},a),l=e.handle,v=e.hoverClass||"hover",s=e.focusClass||"focus",t=e.activeClass||"active",B=!!e.labelHover,w=e.labelHoverClass||"hover",p=(""+e.increaseArea).replace("%","")|0;if("checkbox"==l||l==r)d='input[type="'+l+'"]';-50>p&&(p=-50);g(this);return c.each(function(){var a=f(this);E(a);var c=this, + b=c.id,g=-p+"%",d=100+2*p+"%",d={position:"absolute",top:g,left:g,display:"block",width:d,height:d,margin:0,padding:0,background:"#fff",border:0,opacity:0},g=_mobile?{position:"absolute",visibility:"hidden"}:p?d:{position:"absolute",opacity:0},l="checkbox"==c[_type]?e.checkboxClass||"icheckbox":e.radioClass||"i"+r,z=f(_label+'[for="'+b+'"]').add(a.closest(_label)),u=!!e.aria,y=m+"-"+Math.random().toString(36).substr(2,6),h='
")[_callback]("ifCreated").parent().append(e.insert);d=f('').css(d).appendTo(h);a.data(m,{o:e,s:a.attr("style")}).css(g);e.inheritClass&&h[_add](c.className||"");e.inheritID&&b&&h.attr("id",m+"-"+b);"static"==h.css("position")&&h.css("position","relative");A(a,!0,_update);if(z.length)z.on(_click+".i mouseover.i mouseout.i "+_touch,function(b){var d=b[_type],e=f(this);if(!c[n]){if(d==_click){if(f(b.target).is("a"))return; + A(a,!1,!0)}else B&&(/ut|nd/.test(d)?(h[_remove](v),e[_remove](w)):(h[_add](v),e[_add](w)));if(_mobile)b.stopPropagation();else return!1}});a.on(_click+".i focus.i blur.i keyup.i keydown.i keypress.i",function(b){var d=b[_type];b=b.keyCode;if(d==_click)return!1;if("keydown"==d&&32==b)return c[_type]==r&&c[k]||(c[k]?q(a,k):x(a,k)),!1;if("keyup"==d&&c[_type]==r)!c[k]&&x(a,k);else if(/us|ur/.test(d))h["blur"==d?_remove:_add](s)});d.on(_click+" mousedown mouseup mouseover mouseout "+_touch,function(b){var d= + b[_type],e=/wn|up/.test(d)?t:v;if(!c[n]){if(d==_click)A(a,!1,!0);else{if(/wn|er|in/.test(d))h[_add](e);else h[_remove](e+" "+t);if(z.length&&B&&e==v)z[/ut|nd/.test(d)?_remove:_add](w)}if(_mobile)b.stopPropagation();else return!1}})})}})(window.jQuery||window.Zepto); diff --git a/static/js/plugins/metisMenu/jquery.metisMenu.js b/static/js/plugins/metisMenu/jquery.metisMenu.js new file mode 100644 index 000000000000..3c9499c50f38 --- /dev/null +++ b/static/js/plugins/metisMenu/jquery.metisMenu.js @@ -0,0 +1,120 @@ +/* + * metismenu - v1.1.3 + * Easy menu jQuery plugin for Twitter Bootstrap 3 + * https://github.com/onokumus/metisMenu + * + * Made by Osman Nuri Okumus + * Under MIT License + */ +;(function($, window, document, undefined) { + + var pluginName = "metisMenu", + defaults = { + toggle: true, + doubleTapToGo: false + }; + + function Plugin(element, options) { + this.element = $(element); + this.settings = $.extend({}, defaults, options); + this._defaults = defaults; + this._name = pluginName; + this.init(); + } + + Plugin.prototype = { + init: function() { + + var $this = this.element, + $toggle = this.settings.toggle, + obj = this; + + if (this.isIE() <= 9) { + $this.find("li.active").has("ul").children("ul").collapse("show"); + $this.find("li").not(".active").has("ul").children("ul").collapse("hide"); + } else { + $this.find("li.active").has("ul").children("ul").addClass("collapse in"); + $this.find("li").not(".active").has("ul").children("ul").addClass("collapse"); + } + + //add the "doubleTapToGo" class to active items if needed + if (obj.settings.doubleTapToGo) { + $this.find("li.active").has("ul").children("a").addClass("doubleTapToGo"); + } + + $this.find("li").has("ul").children("a").on("click" + "." + pluginName, function(e) { + e.preventDefault(); + + //Do we need to enable the double tap + if (obj.settings.doubleTapToGo) { + + //if we hit a second time on the link and the href is valid, navigate to that url + if (obj.doubleTapToGo($(this)) && $(this).attr("href") !== "#" && $(this).attr("href") !== "") { + e.stopPropagation(); + document.location = $(this).attr("href"); + return; + } + } + + $(this).parent("li").toggleClass("active").children("ul").collapse("toggle"); + + if ($toggle) { + $(this).parent("li").siblings().removeClass("active").children("ul.in").collapse("hide"); + } + + }); + }, + + isIE: function() { //https://gist.github.com/padolsey/527683 + var undef, + v = 3, + div = document.createElement("div"), + all = div.getElementsByTagName("i"); + + while ( + div.innerHTML = "", + all[0] + ) { + return v > 4 ? v : undef; + } + }, + + //Enable the link on the second click. + doubleTapToGo: function(elem) { + var $this = this.element; + + //if the class "doubleTapToGo" exists, remove it and return + if (elem.hasClass("doubleTapToGo")) { + elem.removeClass("doubleTapToGo"); + return true; + } + + //does not exists, add a new class and return false + if (elem.parent().children("ul").length) { + //first remove all other class + $this.find(".doubleTapToGo").removeClass("doubleTapToGo"); + //add the class on the current element + elem.addClass("doubleTapToGo"); + return false; + } + }, + + remove: function() { + this.element.off("." + pluginName); + this.element.removeData(pluginName); + } + + }; + + $.fn[pluginName] = function(options) { + this.each(function () { + var el = $(this); + if (el.data(pluginName)) { + el.data(pluginName).remove(); + } + el.data(pluginName, new Plugin(this, options)); + }); + return this; + }; + +})(jQuery, window, document); \ No newline at end of file diff --git a/static/js/plugins/pace/pace.min.js b/static/js/plugins/pace/pace.min.js new file mode 100644 index 000000000000..9f7c7dc9bc93 --- /dev/null +++ b/static/js/plugins/pace/pace.min.js @@ -0,0 +1,2 @@ +/*! pace 0.5.1 */ +(function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W=[].slice,X={}.hasOwnProperty,Y=function(a,b){function c(){this.constructor=a}for(var d in b)X.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},Z=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};for(t={catchupTime:500,initialRate:.03,minTime:500,ghostTime:500,maxProgressPerFrame:10,easeFactor:1.25,startOnPageLoad:!0,restartOnPushState:!0,restartOnRequestAfter:500,target:"body",elements:{checkInterval:100,selectors:["body"]},eventLag:{minSamples:10,sampleCount:3,lagThreshold:3},ajax:{trackMethods:["GET"],trackWebSockets:!0,ignoreURLs:[]}},B=function(){var a;return null!=(a="undefined"!=typeof performance&&null!==performance?"function"==typeof performance.now?performance.now():void 0:void 0)?a:+new Date},D=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame,s=window.cancelAnimationFrame||window.mozCancelAnimationFrame,null==D&&(D=function(a){return setTimeout(a,50)},s=function(a){return clearTimeout(a)}),F=function(a){var b,c;return b=B(),(c=function(){var d;return d=B()-b,d>=33?(b=B(),a(d,function(){return D(c)})):setTimeout(c,33-d)})()},E=function(){var a,b,c;return c=arguments[0],b=arguments[1],a=3<=arguments.length?W.call(arguments,2):[],"function"==typeof c[b]?c[b].apply(c,a):c[b]},u=function(){var a,b,c,d,e,f,g;for(b=arguments[0],d=2<=arguments.length?W.call(arguments,1):[],f=0,g=d.length;g>f;f++)if(c=d[f])for(a in c)X.call(c,a)&&(e=c[a],null!=b[a]&&"object"==typeof b[a]&&null!=e&&"object"==typeof e?u(b[a],e):b[a]=e);return b},p=function(a){var b,c,d,e,f;for(c=b=0,e=0,f=a.length;f>e;e++)d=a[e],c+=Math.abs(d),b++;return c/b},w=function(a,b){var c,d,e;if(null==a&&(a="options"),null==b&&(b=!0),e=document.querySelector("[data-pace-"+a+"]")){if(c=e.getAttribute("data-pace-"+a),!b)return c;try{return JSON.parse(c)}catch(f){return d=f,"undefined"!=typeof console&&null!==console?console.error("Error parsing inline pace options",d):void 0}}},g=function(){function a(){}return a.prototype.on=function(a,b,c,d){var e;return null==d&&(d=!1),null==this.bindings&&(this.bindings={}),null==(e=this.bindings)[a]&&(e[a]=[]),this.bindings[a].push({handler:b,ctx:c,once:d})},a.prototype.once=function(a,b,c){return this.on(a,b,c,!0)},a.prototype.off=function(a,b){var c,d,e;if(null!=(null!=(d=this.bindings)?d[a]:void 0)){if(null==b)return delete this.bindings[a];for(c=0,e=[];cP;P++)J=T[P],C[J]===!0&&(C[J]=t[J]);i=function(a){function b(){return U=b.__super__.constructor.apply(this,arguments)}return Y(b,a),b}(Error),b=function(){function a(){this.progress=0}return a.prototype.getElement=function(){var a;if(null==this.el){if(a=document.querySelector(C.target),!a)throw new i;this.el=document.createElement("div"),this.el.className="pace pace-active",document.body.className=document.body.className.replace(/pace-done/g,""),document.body.className+=" pace-running",this.el.innerHTML='
\n
\n
\n
',null!=a.firstChild?a.insertBefore(this.el,a.firstChild):a.appendChild(this.el)}return this.el},a.prototype.finish=function(){var a;return a=this.getElement(),a.className=a.className.replace("pace-active",""),a.className+=" pace-inactive",document.body.className=document.body.className.replace("pace-running",""),document.body.className+=" pace-done"},a.prototype.update=function(a){return this.progress=a,this.render()},a.prototype.destroy=function(){try{this.getElement().parentNode.removeChild(this.getElement())}catch(a){i=a}return this.el=void 0},a.prototype.render=function(){var a,b;return null==document.querySelector(C.target)?!1:(a=this.getElement(),a.children[0].style.width=""+this.progress+"%",(!this.lastRenderedProgress||this.lastRenderedProgress|0!==this.progress|0)&&(a.children[0].setAttribute("data-progress-text",""+(0|this.progress)+"%"),this.progress>=100?b="99":(b=this.progress<10?"0":"",b+=0|this.progress),a.children[0].setAttribute("data-progress",""+b)),this.lastRenderedProgress=this.progress)},a.prototype.done=function(){return this.progress>=100},a}(),h=function(){function a(){this.bindings={}}return a.prototype.trigger=function(a,b){var c,d,e,f,g;if(null!=this.bindings[a]){for(f=this.bindings[a],g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(c.call(this,b));return g}},a.prototype.on=function(a,b){var c;return null==(c=this.bindings)[a]&&(c[a]=[]),this.bindings[a].push(b)},a}(),O=window.XMLHttpRequest,N=window.XDomainRequest,M=window.WebSocket,v=function(a,b){var c,d,e,f;f=[];for(d in b.prototype)try{e=b.prototype[d],null==a[d]&&"function"!=typeof e?f.push(a[d]=e):f.push(void 0)}catch(g){c=g}return f},z=[],Pace.ignore=function(){var a,b,c;return b=arguments[0],a=2<=arguments.length?W.call(arguments,1):[],z.unshift("ignore"),c=b.apply(null,a),z.shift(),c},Pace.track=function(){var a,b,c;return b=arguments[0],a=2<=arguments.length?W.call(arguments,1):[],z.unshift("track"),c=b.apply(null,a),z.shift(),c},I=function(a){var b;if(null==a&&(a="GET"),"track"===z[0])return"force";if(!z.length&&C.ajax){if("socket"===a&&C.ajax.trackWebSockets)return!0;if(b=a.toUpperCase(),Z.call(C.ajax.trackMethods,b)>=0)return!0}return!1},j=function(a){function b(){var a,c=this;b.__super__.constructor.apply(this,arguments),a=function(a){var b;return b=a.open,a.open=function(d,e){return I(d)&&c.trigger("request",{type:d,url:e,request:a}),b.apply(a,arguments)}},window.XMLHttpRequest=function(b){var c;return c=new O(b),a(c),c},v(window.XMLHttpRequest,O),null!=N&&(window.XDomainRequest=function(){var b;return b=new N,a(b),b},v(window.XDomainRequest,N)),null!=M&&C.ajax.trackWebSockets&&(window.WebSocket=function(a,b){var d;return d=null!=b?new M(a,b):new M(a),I("socket")&&c.trigger("request",{type:"socket",url:a,protocols:b,request:d}),d},v(window.WebSocket,M))}return Y(b,a),b}(h),Q=null,x=function(){return null==Q&&(Q=new j),Q},H=function(a){var b,c,d,e;for(e=C.ajax.ignoreURLs,c=0,d=e.length;d>c;c++)if(b=e[c],"string"==typeof b){if(-1!==a.indexOf(b))return!0}else if(b.test(a))return!0;return!1},x().on("request",function(b){var c,d,e,f,g;return f=b.type,e=b.request,g=b.url,H(g)?void 0:Pace.running||C.restartOnRequestAfter===!1&&"force"!==I(f)?void 0:(d=arguments,c=C.restartOnRequestAfter||0,"boolean"==typeof c&&(c=0),setTimeout(function(){var b,c,g,h,i,j;if(b="socket"===f?e.readyState<2:0<(h=e.readyState)&&4>h){for(Pace.restart(),i=Pace.sources,j=[],c=0,g=i.length;g>c;c++){if(J=i[c],J instanceof a){J.watch.apply(J,d);break}j.push(void 0)}return j}},c))}),a=function(){function a(){var a=this;this.elements=[],x().on("request",function(){return a.watch.apply(a,arguments)})}return a.prototype.watch=function(a){var b,c,d,e;return d=a.type,b=a.request,e=a.url,H(e)?void 0:(c="socket"===d?new m(b):new n(b),this.elements.push(c))},a}(),n=function(){function a(a){var b,c,d,e,f,g,h=this;if(this.progress=0,null!=window.ProgressEvent)for(c=null,a.addEventListener("progress",function(a){return h.progress=a.lengthComputable?100*a.loaded/a.total:h.progress+(100-h.progress)/2}),g=["load","abort","timeout","error"],d=0,e=g.length;e>d;d++)b=g[d],a.addEventListener(b,function(){return h.progress=100});else f=a.onreadystatechange,a.onreadystatechange=function(){var b;return 0===(b=a.readyState)||4===b?h.progress=100:3===a.readyState&&(h.progress=50),"function"==typeof f?f.apply(null,arguments):void 0}}return a}(),m=function(){function a(a){var b,c,d,e,f=this;for(this.progress=0,e=["error","open"],c=0,d=e.length;d>c;c++)b=e[c],a.addEventListener(b,function(){return f.progress=100})}return a}(),d=function(){function a(a){var b,c,d,f;for(null==a&&(a={}),this.elements=[],null==a.selectors&&(a.selectors=[]),f=a.selectors,c=0,d=f.length;d>c;c++)b=f[c],this.elements.push(new e(b))}return a}(),e=function(){function a(a){this.selector=a,this.progress=0,this.check()}return a.prototype.check=function(){var a=this;return document.querySelector(this.selector)?this.done():setTimeout(function(){return a.check()},C.elements.checkInterval)},a.prototype.done=function(){return this.progress=100},a}(),c=function(){function a(){var a,b,c=this;this.progress=null!=(b=this.states[document.readyState])?b:100,a=document.onreadystatechange,document.onreadystatechange=function(){return null!=c.states[document.readyState]&&(c.progress=c.states[document.readyState]),"function"==typeof a?a.apply(null,arguments):void 0}}return a.prototype.states={loading:0,interactive:50,complete:100},a}(),f=function(){function a(){var a,b,c,d,e,f=this;this.progress=0,a=0,e=[],d=0,c=B(),b=setInterval(function(){var g;return g=B()-c-50,c=B(),e.push(g),e.length>C.eventLag.sampleCount&&e.shift(),a=p(e),++d>=C.eventLag.minSamples&&a=100&&(this.done=!0),b===this.last?this.sinceLastUpdate+=a:(this.sinceLastUpdate&&(this.rate=(b-this.last)/this.sinceLastUpdate),this.catchup=(b-this.progress)/C.catchupTime,this.sinceLastUpdate=0,this.last=b),b>this.progress&&(this.progress+=this.catchup*a),c=1-Math.pow(this.progress/100,C.easeFactor),this.progress+=c*this.rate*a,this.progress=Math.min(this.lastProgress+C.maxProgressPerFrame,this.progress),this.progress=Math.max(0,this.progress),this.progress=Math.min(100,this.progress),this.lastProgress=this.progress,this.progress},a}(),K=null,G=null,q=null,L=null,o=null,r=null,Pace.running=!1,y=function(){return C.restartOnPushState?Pace.restart():void 0},null!=window.history.pushState&&(S=window.history.pushState,window.history.pushState=function(){return y(),S.apply(window.history,arguments)}),null!=window.history.replaceState&&(V=window.history.replaceState,window.history.replaceState=function(){return y(),V.apply(window.history,arguments)}),k={ajax:a,elements:d,document:c,eventLag:f},(A=function(){var a,c,d,e,f,g,h,i;for(Pace.sources=K=[],g=["ajax","elements","document","eventLag"],c=0,e=g.length;e>c;c++)a=g[c],C[a]!==!1&&K.push(new k[a](C[a]));for(i=null!=(h=C.extraSources)?h:[],d=0,f=i.length;f>d;d++)J=i[d],K.push(new J(C));return Pace.bar=q=new b,G=[],L=new l})(),Pace.stop=function(){return Pace.trigger("stop"),Pace.running=!1,q.destroy(),r=!0,null!=o&&("function"==typeof s&&s(o),o=null),A()},Pace.restart=function(){return Pace.trigger("restart"),Pace.stop(),Pace.start()},Pace.go=function(){var a;return Pace.running=!0,q.render(),a=B(),r=!1,o=F(function(b,c){var d,e,f,g,h,i,j,k,m,n,o,p,s,t,u,v;for(k=100-q.progress,e=o=0,f=!0,i=p=0,t=K.length;t>p;i=++p)for(J=K[i],n=null!=G[i]?G[i]:G[i]=[],h=null!=(v=J.elements)?v:[J],j=s=0,u=h.length;u>s;j=++s)g=h[j],m=null!=n[j]?n[j]:n[j]=new l(g),f&=m.done,m.done||(e++,o+=m.tick(b));return d=o/e,q.update(L.tick(b,d)),q.done()||f||r?(q.update(100),Pace.trigger("done"),setTimeout(function(){return q.finish(),Pace.running=!1,Pace.trigger("hide")},Math.max(C.ghostTime,Math.max(C.minTime-(B()-a),0)))):c()})},Pace.start=function(a){u(C,a),Pace.running=!0;try{q.render()}catch(b){i=b}return document.querySelector(".pace")?(Pace.trigger("start"),Pace.go()):setTimeout(Pace.start,50)},"function"==typeof define&&define.amd?define(function(){return Pace}):"object"==typeof exports?module.exports=Pace:C.startOnPageLoad&&Pace.start()}).call(this); \ No newline at end of file diff --git a/static/js/plugins/peity/jquery.peity.min.js b/static/js/plugins/peity/jquery.peity.min.js new file mode 100644 index 000000000000..085b72507862 --- /dev/null +++ b/static/js/plugins/peity/jquery.peity.min.js @@ -0,0 +1,13 @@ +// Peity jQuery plugin version 2.0.3 +// (c) 2014 Ben Pickles +// +// http://benpickles.github.io/peity +// +// Released under MIT license. +(function(e,q,h){var o=function(a,b){var c=q.createElementNS("http://www.w3.org/2000/svg",a);e.each(b,function(a,b){c.setAttribute(a,b)});return c},t="createElementNS"in q&&o("svg",{}).createSVGRect,r=1/(window.devicePixelRatio||1),j=e.fn.peity=function(a,b){t&&this.each(function(){var c=e(this),d=c.data("peity");if(d)a&&(d.type=a),e.extend(d.opts,b);else{var f=j.defaults[a],g={};e.each(c.data(),function(a,b){a in f&&(g[a]=b)});var h=e.extend({},f,g,b),d=new s(c,a,h);c.change(function(){d.draw()}).data("peity", + d)}d.draw()});return this},s=function(a,b,c){this.$el=a;this.type=b;this.opts=c},m=s.prototype;m.draw=function(){j.graphers[this.type].call(this,this.opts)};m.fill=function(){var a=this.opts.fill,b=a;e.isFunction(b)||(b=function(b,d){return a[d%a.length]});return b};m.prepare=function(a,b){var c;this.svg?c=e(this.svg).empty():(this.svg=o("svg",{"class":"peity"}),this.$el.hide().after(this.svg),c=e(this.svg).data("peity",this));this.svg.setAttribute("height",b);this.svg.setAttribute("width",a);return c}; + m.values=function(){return e.map(this.$el.text().split(this.opts.delimiter),function(a){return parseFloat(a)})};j.defaults={};j.graphers={};j.register=function(a,b,c){this.defaults[a]=b;this.graphers[a]=c};j.register("pie",{delimiter:null,diameter:16,fill:["#ff9900","#fff4dd","#ffc66e"]},function(a){if(!a.delimiter){var b=this.$el.text().match(/[^0-9\.]/);a.delimiter=b?b[0]:","}b=this.values();if("/"==a.delimiter)var c=b[0],b=[c,h.max(0,b[1]-c)];for(var d=0,c=b.length,f=0;de?1:0,1,q,r,"Z"].join(" ")});i=l}k.setAttribute("fill",j.call(this,n,d,b));this.svg.appendChild(k)}}});j.register("line",{delimiter:",",fill:"#c6d9fd",height:16,max:null, + min:0,stroke:"#4d89f9",strokeWidth:1,width:32},function(a){var b=this.values();1==b.length&&b.push(b[0]);for(var c=h.max.apply(h,b.concat([a.max])),d=h.min.apply(h,b.concat([a.min])),f=this.prepare(a.width,a.height),g=f.width(),f=f.height()-a.strokeWidth,e=g/(b.length-1),c=c-d,j=0==c?f:f/c,m=f+d*j,c=[0,m],i=0;i=d&&0k&&(l+=k,k=-k);n=o("rect",{fill:m.call(this,n,i,b),x:i*g,y:l,width:g-a,height:k});this.svg.appendChild(n)}})})(jQuery,document,Math); diff --git a/static/js/plugins/slimscroll/jquery.slimscroll.js b/static/js/plugins/slimscroll/jquery.slimscroll.js new file mode 100644 index 000000000000..2ea5b0801ccb --- /dev/null +++ b/static/js/plugins/slimscroll/jquery.slimscroll.js @@ -0,0 +1,464 @@ +/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la) + * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) + * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. + * + * Version: 1.3.0 + * + */ +(function($) { + + jQuery.fn.extend({ + slimScroll: function(options) { + + var defaults = { + + // width in pixels of the visible scroll area + width : 'auto', + + // height in pixels of the visible scroll area + height : '250px', + + // width in pixels of the scrollbar and rail + size : '7px', + + // scrollbar color, accepts any hex/color value + color: '#000', + + // scrollbar position - left/right + position : 'right', + + // distance in pixels between the side edge and the scrollbar + distance : '1px', + + // default scroll position on load - top / bottom / $('selector') + start : 'top', + + // sets scrollbar opacity + opacity : .4, + + // enables always-on mode for the scrollbar + alwaysVisible : false, + + // check if we should hide the scrollbar when user is hovering over + disableFadeOut : false, + + // sets visibility of the rail + railVisible : false, + + // sets rail color + railColor : '#333', + + // sets rail opacity + railOpacity : .2, + + // whether we should use jQuery UI Draggable to enable bar dragging + railDraggable : true, + + // defautlt CSS class of the slimscroll rail + railClass : 'slimScrollRail', + + // defautlt CSS class of the slimscroll bar + barClass : 'slimScrollBar', + + // defautlt CSS class of the slimscroll wrapper + wrapperClass : 'slimScrollDiv', + + // check if mousewheel should scroll the window if we reach top/bottom + allowPageScroll : false, + + // scroll amount applied to each mouse wheel step + wheelStep : 20, + + // scroll amount applied when user is using gestures + touchScrollStep : 200, + + // sets border radius + borderRadius: '7px', + + // sets border radius of the rail + railBorderRadius : '7px' + }; + + var o = $.extend(defaults, options); + + // do it for every element that matches selector + this.each(function(){ + + var isOverPanel, isOverBar, isDragg, queueHide, touchDif, + barHeight, percentScroll, lastScroll, + divS = '
', + minBarHeight = 30, + releaseScroll = false; + + // used in event handlers and for better minification + var me = $(this); + + // ensure we are not binding it again + if (me.parent().hasClass(o.wrapperClass)) + { + // start from last bar position + var offset = me.scrollTop(); + + // find bar and rail + bar = me.parent().find('.' + o.barClass); + rail = me.parent().find('.' + o.railClass); + + getBarHeight(); + + // check if we should scroll existing instance + if ($.isPlainObject(options)) + { + // Pass height: auto to an existing slimscroll object to force a resize after contents have changed + if ( 'height' in options && options.height == 'auto' ) { + me.parent().css('height', 'auto'); + me.css('height', 'auto'); + var height = me.parent().parent().height(); + me.parent().css('height', height); + me.css('height', height); + } + + if ('scrollTo' in options) + { + // jump to a static point + offset = parseInt(o.scrollTo); + } + else if ('scrollBy' in options) + { + // jump by value pixels + offset += parseInt(o.scrollBy); + } + else if ('destroy' in options) + { + // remove slimscroll elements + bar.remove(); + rail.remove(); + me.unwrap(); + return; + } + + // scroll content by the given offset + scrollContent(offset, false, true); + } + + return; + } + + // optionally set height to the parent's height + o.height = (o.height == 'auto') ? me.parent().height() : o.height; + + // wrap content + var wrapper = $(divS) + .addClass(o.wrapperClass) + .css({ + position: 'relative', + overflow: 'hidden', + width: o.width, + height: o.height + }); + + // update style for the div + me.css({ + overflow: 'hidden', + width: o.width, + height: o.height + }); + + // create scrollbar rail + var rail = $(divS) + .addClass(o.railClass) + .css({ + width: o.size, + height: '100%', + position: 'absolute', + top: 0, + display: (o.alwaysVisible && o.railVisible) ? 'block' : 'none', + 'border-radius': o.railBorderRadius, + background: o.railColor, + opacity: o.railOpacity, + zIndex: 90 + }); + + // create scrollbar + var bar = $(divS) + .addClass(o.barClass) + .css({ + background: o.color, + width: o.size, + position: 'absolute', + top: 0, + opacity: o.opacity, + display: o.alwaysVisible ? 'block' : 'none', + 'border-radius' : o.borderRadius, + BorderRadius: o.borderRadius, + MozBorderRadius: o.borderRadius, + WebkitBorderRadius: o.borderRadius, + zIndex: 99 + }); + + // set position + var posCss = (o.position == 'right') ? { right: o.distance } : { left: o.distance }; + rail.css(posCss); + bar.css(posCss); + + // wrap it + me.wrap(wrapper); + + // append to parent div + me.parent().append(bar); + me.parent().append(rail); + + // make it draggable and no longer dependent on the jqueryUI + if (o.railDraggable){ + bar.bind("mousedown", function(e) { + var $doc = $(document); + isDragg = true; + t = parseFloat(bar.css('top')); + pageY = e.pageY; + + $doc.bind("mousemove.slimscroll", function(e){ + currTop = t + e.pageY - pageY; + bar.css('top', currTop); + scrollContent(0, bar.position().top, false);// scroll content + }); + + $doc.bind("mouseup.slimscroll", function(e) { + isDragg = false;hideBar(); + $doc.unbind('.slimscroll'); + }); + return false; + }).bind("selectstart.slimscroll", function(e){ + e.stopPropagation(); + e.preventDefault(); + return false; + }); + } + + // on rail over + rail.hover(function(){ + showBar(); + }, function(){ + hideBar(); + }); + + // on bar over + bar.hover(function(){ + isOverBar = true; + }, function(){ + isOverBar = false; + }); + + // show on parent mouseover + me.hover(function(){ + isOverPanel = true; + showBar(); + hideBar(); + }, function(){ + isOverPanel = false; + hideBar(); + }); + + // support for mobile + me.bind('touchstart', function(e,b){ + if (e.originalEvent.touches.length) + { + // record where touch started + touchDif = e.originalEvent.touches[0].pageY; + } + }); + + me.bind('touchmove', function(e){ + // prevent scrolling the page if necessary + if(!releaseScroll) + { + e.originalEvent.preventDefault(); + } + if (e.originalEvent.touches.length) + { + // see how far user swiped + var diff = (touchDif - e.originalEvent.touches[0].pageY) / o.touchScrollStep; + // scroll content + scrollContent(diff, true); + touchDif = e.originalEvent.touches[0].pageY; + } + }); + + // set up initial height + getBarHeight(); + + // check start position + if (o.start === 'bottom') + { + // scroll content to bottom + bar.css({ top: me.outerHeight() - bar.outerHeight() }); + scrollContent(0, true); + } + else if (o.start !== 'top') + { + // assume jQuery selector + scrollContent($(o.start).position().top, null, true); + + // make sure bar stays hidden + if (!o.alwaysVisible) { bar.hide(); } + } + + // attach scroll events + attachWheel(); + + function _onWheel(e) + { + // use mouse wheel only when mouse is over + if (!isOverPanel) { return; } + + var e = e || window.event; + + var delta = 0; + if (e.wheelDelta) { delta = -e.wheelDelta/120; } + if (e.detail) { delta = e.detail / 3; } + + var target = e.target || e.srcTarget || e.srcElement; + if ($(target).closest('.' + o.wrapperClass).is(me.parent())) { + // scroll content + scrollContent(delta, true); + } + + // stop window scroll + if (e.preventDefault && !releaseScroll) { e.preventDefault(); } + if (!releaseScroll) { e.returnValue = false; } + } + + function scrollContent(y, isWheel, isJump) + { + releaseScroll = false; + var delta = y; + var maxTop = me.outerHeight() - bar.outerHeight(); + + if (isWheel) + { + // move bar with mouse wheel + delta = parseInt(bar.css('top')) + y * parseInt(o.wheelStep) / 100 * bar.outerHeight(); + + // move bar, make sure it doesn't go out + delta = Math.min(Math.max(delta, 0), maxTop); + + // if scrolling down, make sure a fractional change to the + // scroll position isn't rounded away when the scrollbar's CSS is set + // this flooring of delta would happened automatically when + // bar.css is set below, but we floor here for clarity + delta = (y > 0) ? Math.ceil(delta) : Math.floor(delta); + + // scroll the scrollbar + bar.css({ top: delta + 'px' }); + } + + // calculate actual scroll amount + percentScroll = parseInt(bar.css('top')) / (me.outerHeight() - bar.outerHeight()); + delta = percentScroll * (me[0].scrollHeight - me.outerHeight()); + + if (isJump) + { + delta = y; + var offsetTop = delta / me[0].scrollHeight * me.outerHeight(); + offsetTop = Math.min(Math.max(offsetTop, 0), maxTop); + bar.css({ top: offsetTop + 'px' }); + } + + // scroll content + me.scrollTop(delta); + + // fire scrolling event + me.trigger('slimscrolling', ~~delta); + + // ensure bar is visible + showBar(); + + // trigger hide when scroll is stopped + hideBar(); + } + + function attachWheel() + { + if (window.addEventListener) + { + this.addEventListener('DOMMouseScroll', _onWheel, false ); + this.addEventListener('mousewheel', _onWheel, false ); + this.addEventListener('MozMousePixelScroll', _onWheel, false ); + } + else + { + document.attachEvent("onmousewheel", _onWheel) + } + } + + function getBarHeight() + { + // calculate scrollbar height and make sure it is not too small + barHeight = Math.max((me.outerHeight() / me[0].scrollHeight) * me.outerHeight(), minBarHeight); + bar.css({ height: barHeight + 'px' }); + + // hide scrollbar if content is not long enough + var display = barHeight == me.outerHeight() ? 'none' : 'block'; + bar.css({ display: display }); + } + + function showBar() + { + // recalculate bar height + getBarHeight(); + clearTimeout(queueHide); + + // when bar reached top or bottom + if (percentScroll == ~~percentScroll) + { + //release wheel + releaseScroll = o.allowPageScroll; + + // publish approporiate event + if (lastScroll != percentScroll) + { + var msg = (~~percentScroll == 0) ? 'top' : 'bottom'; + me.trigger('slimscroll', msg); + } + } + else + { + releaseScroll = false; + } + lastScroll = percentScroll; + + // show only when required + if(barHeight >= me.outerHeight()) { + //allow window scroll + releaseScroll = true; + return; + } + bar.stop(true,true).fadeIn('fast'); + if (o.railVisible) { rail.stop(true,true).fadeIn('fast'); } + } + + function hideBar() + { + // only hide when options allow it + if (!o.alwaysVisible) + { + queueHide = setTimeout(function(){ + if (!(o.disableFadeOut && isOverPanel) && !isOverBar && !isDragg) + { + bar.fadeOut('slow'); + rail.fadeOut('slow'); + } + }, 1000); + } + } + + }); + + // maintain chainability + return this; + } + }); + + jQuery.fn.extend({ + slimscroll: jQuery.fn.slimScroll + }); + +})(jQuery); diff --git a/static/js/plugins/slimscroll/jquery.slimscroll.min.js b/static/js/plugins/slimscroll/jquery.slimscroll.min.js new file mode 100644 index 000000000000..26220d6b2bdd --- /dev/null +++ b/static/js/plugins/slimscroll/jquery.slimscroll.min.js @@ -0,0 +1,16 @@ +/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la) + * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) + * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. + * + * Version: 1.3.0 + * + */ +(function(f){jQuery.fn.extend({slimScroll:function(h){var a=f.extend({width:"auto",height:"250px",size:"7px",color:"#000",position:"right",distance:"1px",start:"top",opacity:0.4,alwaysVisible:!1,disableFadeOut:!1,railVisible:!1,railColor:"#333",railOpacity:0.2,railDraggable:!0,railClass:"slimScrollRail",barClass:"slimScrollBar",wrapperClass:"slimScrollDiv",allowPageScroll:!1,wheelStep:20,touchScrollStep:200,borderRadius:"7px",railBorderRadius:"7px"},h);this.each(function(){function r(d){if(s){d=d|| +window.event;var c=0;d.wheelDelta&&(c=-d.wheelDelta/120);d.detail&&(c=d.detail/3);f(d.target||d.srcTarget||d.srcElement).closest("."+a.wrapperClass).is(b.parent())&&m(c,!0);d.preventDefault&&!k&&d.preventDefault();k||(d.returnValue=!1)}}function m(d,f,h){k=!1;var e=d,g=b.outerHeight()-c.outerHeight();f&&(e=parseInt(c.css("top"))+d*parseInt(a.wheelStep)/100*c.outerHeight(),e=Math.min(Math.max(e,0),g),e=0=b.outerHeight()?k=!0:(c.stop(!0,!0).fadeIn("fast"),a.railVisible&&g.stop(!0,!0).fadeIn("fast"))}function p(){a.alwaysVisible||(A=setTimeout(function(){a.disableFadeOut&&s||(x||y)||(c.fadeOut("slow"),g.fadeOut("slow"))},1E3))}var s,x,y,A,z,u,l,B,D=30,k=!1,b=f(this);if(b.parent().hasClass(a.wrapperClass)){var n=b.scrollTop(), +c=b.parent().find("."+a.barClass),g=b.parent().find("."+a.railClass);w();if(f.isPlainObject(h)){if("height"in h&&"auto"==h.height){b.parent().css("height","auto");b.css("height","auto");var q=b.parent().parent().height();b.parent().css("height",q);b.css("height",q)}if("scrollTo"in h)n=parseInt(a.scrollTo);else if("scrollBy"in h)n+=parseInt(a.scrollBy);else if("destroy"in h){c.remove();g.remove();b.unwrap();return}m(n,!1,!0)}}else{a.height="auto"==a.height?b.parent().height():a.height;n=f("
").addClass(a.wrapperClass).css({position:"relative", +overflow:"hidden",width:a.width,height:a.height});b.css({overflow:"hidden",width:a.width,height:a.height});var g=f("
").addClass(a.railClass).css({width:a.size,height:"100%",position:"absolute",top:0,display:a.alwaysVisible&&a.railVisible?"block":"none","border-radius":a.railBorderRadius,background:a.railColor,opacity:a.railOpacity,zIndex:90}),c=f("
").addClass(a.barClass).css({background:a.color,width:a.size,position:"absolute",top:0,opacity:a.opacity,display:a.alwaysVisible? +"block":"none","border-radius":a.borderRadius,BorderRadius:a.borderRadius,MozBorderRadius:a.borderRadius,WebkitBorderRadius:a.borderRadius,zIndex:99}),q="right"==a.position?{right:a.distance}:{left:a.distance};g.css(q);c.css(q);b.wrap(n);b.parent().append(c);b.parent().append(g);a.railDraggable&&c.bind("mousedown",function(a){var b=f(document);y=!0;t=parseFloat(c.css("top"));pageY=a.pageY;b.bind("mousemove.slimscroll",function(a){currTop=t+a.pageY-pageY;c.css("top",currTop);m(0,c.position().top,!1)}); +b.bind("mouseup.slimscroll",function(a){y=!1;p();b.unbind(".slimscroll")});return!1}).bind("selectstart.slimscroll",function(a){a.stopPropagation();a.preventDefault();return!1});g.hover(function(){v()},function(){p()});c.hover(function(){x=!0},function(){x=!1});b.hover(function(){s=!0;v();p()},function(){s=!1;p()});b.bind("touchstart",function(a,b){a.originalEvent.touches.length&&(z=a.originalEvent.touches[0].pageY)});b.bind("touchmove",function(b){k||b.originalEvent.preventDefault();b.originalEvent.touches.length&& +(m((z-b.originalEvent.touches[0].pageY)/a.touchScrollStep,!0),z=b.originalEvent.touches[0].pageY)});w();"bottom"===a.start?(c.css({top:b.outerHeight()-c.outerHeight()}),m(0,!0)):"top"!==a.start&&(m(f(a.start).position().top,null,!0),a.alwaysVisible||c.hide());C()}});return this}});jQuery.fn.extend({slimscroll:jQuery.fn.slimScroll})})(jQuery); \ No newline at end of file diff --git a/static/js/validator/images/loading.gif b/static/js/validator/images/loading.gif new file mode 100644 index 000000000000..6e5bace6e654 Binary files /dev/null and b/static/js/validator/images/loading.gif differ diff --git a/static/js/validator/images/validator_default.png b/static/js/validator/images/validator_default.png new file mode 100644 index 000000000000..5a9564095dcd Binary files /dev/null and b/static/js/validator/images/validator_default.png differ diff --git a/static/js/validator/images/validator_simple.png b/static/js/validator/images/validator_simple.png new file mode 100644 index 000000000000..2470db588f40 Binary files /dev/null and b/static/js/validator/images/validator_simple.png differ diff --git a/static/js/validator/jquery.validator.js b/static/js/validator/jquery.validator.js new file mode 100644 index 000000000000..20a83dc9e547 --- /dev/null +++ b/static/js/validator/jquery.validator.js @@ -0,0 +1,5 @@ +/*! nice Validator 0.7.3 + * (c) 2012-2014 Jony Zhang , MIT Licensed + * http://niceue.com/validator/ + */ +!function(e,t){"use strict";function i(n,s){var r=this;return!r instanceof i?new i(n,s):(r.$el=e(n),r._init(n,s),t)}function n(e,t){var i=t?t===!0?this:t:n.prototype;if(z(e))for(var s in e)i[s]=r(e[s])}function s(e,t){var i=t?t===!0?this:t:s.prototype;if(z(e))for(var n in e){if(!e[n])return;i[n]=e[n]}}function r(t){switch(e.type(t)){case"function":return t;case"array":return function(e){return t[0].test(e.value)||t[1]||!1};case"regexp":return function(e){return t.test(e.value)}}}function a(t){var i="";return e.map(t.split(" "),function(e){i+=","+("#"===e.charAt(0)?e:'[name="'+e+'"]')}),i.substring(1)}function l(t){var i;if(t&&t.tagName){switch(t.tagName){case"INPUT":case"SELECT":case"TEXTAREA":case"BUTTON":case"FIELDSET":i=t.form||e(t).closest("."+k);break;case"FORM":i=t;break;default:i=e(t).closest("."+k)}return e(i).data(h)||e(i)[h]().data(h)}}function u(e){var t,i=e.currentTarget;i.form&&null===K(i.form,q)&&(t=l(i),t?(t._parse(i),t["_"+e.type](e)):K(i,V,null))}function o(i,n){var s=e.trim(K(i,V+"-"+n));if(s)return s=Function("return "+s)(),s?r(s):t}function d(e,t,i,n){var s=t.msg,r=t._r;return z(s)&&(s=s[r]),Q(s)||(s=K(e,A+"-"+r)||K(e,A)||i||(n?Q(n)?n:n[r]:"")),s}function c(e){var t;return e&&(t=H.exec(e)),t?t[1]:""}function f(e){return"INPUT"===e.tagName&&"checkbox"===e.type||"radio"===e.type}function g(e){return Date.parse(e.replace(/\.|\-/g,"/"))}var p,m,h="validator",v="."+h,y=".rule",_=".field",b=".form",k="nice-"+h,w="n-ok",M="n-error",O="n-tip",$="n-loading",x="msg-box",C="aria-required",F="aria-invalid",V="data-rule",A="data-msg",R="data-tip",T="data-ok",S="data-target",E="data-inputstatus",q="novalidate",N=":verifiable",j=/(!?)\s?(\w+)(?:\[\s*(.*?\]?)\s*\]|\(\s*(.*?\)?)\s*\))?\s*(;|\||&)?/g,D=/(\w+)(?:\[\s*(.*?\]?)\s*\]|\(\s*(.*?\)?)\s*\))?/,I=/(?:([^:;\(\[]*):)?(.*)/,U=/[^\x00-\xff]/g,H=/^.*(top|right|bottom|left).*$/,L=/(?:(post|get):)?(.+)/i,P=/<|>/g,W=e.noop,B=e.proxy,X=e.isFunction,J=e.isArray,Q=function(e){return"string"==typeof e},z=function(e){return e&&"[object Object]"===Object.prototype.toString.call(e)},G=!window.XMLHttpRequest,K=function(e,i,n){return n===t?e.getAttribute(i):(null===n?e.removeAttribute(i):e.setAttribute(i,""+n),t)},Y=window.console||{log:W,info:W},Z={debug:0,timely:1,theme:"default",ignore:"",focusInvalid:!0,beforeSubmit:W,validClass:"n-valid",invalidClass:"n-invalid",msgWrapper:"span",msgMaker:function(e){var t,i={error:M,ok:w,tip:O,loading:$}[e.type];return t='',t+=e.arrow+e.icon+''+e.msg+"",t+=""},msgIcon:'',msgArrow:"",msgClass:"",defaultMsg:"{0} is not valid.",loadingMsg:"Validating..."},et={"default":{formClass:"n-default",msgClass:"n-right",showOk:""}};e.fn[h]=function(t){var n=this,s=arguments;return n.is(":input")?n:(!n.is("form")&&(n=this.find("form")),!n.length&&(n=this),n.each(function(){var n=e(this).data(h);if(n)if(Q(t)){if("_"===t.charAt(0))return;n[t].apply(n,Array.prototype.slice.call(s,1))}else t&&(n._reset(!0),n._init(this,t));else new i(this,t)}),this)},e.fn.isValid=function(e,t){var i,n,s=l(this[0]),r=X(e);return s?(s.checkOnly=!!t,n=s.options,i=s._multiValidate(this.is(":input")?this:this.find(N),function(t){t||!n.focusInvalid||s.checkOnly||s.$el.find(":input["+F+"]:first").focus(),r&&e.call(null,t),s.checkOnly=!1}),r?this:i):!0},e.expr[":"].verifiable=function(e){var t=e.nodeName.toLowerCase();return("input"===t&&!{submit:1,button:1,reset:1,image:1}[e.type]||"select"===t||"textarea"===t)&&e.disabled===!1},i.prototype={_init:function(i,r){var l,u,o,d=this;if(X(r)&&(r={valid:r}),r=r||{},o=K(i,"data-"+h+"-option"),o=o&&"{"===o.charAt(0)?Function("return "+o)():{},u=et[r.theme||o.theme||Z.theme],l=d.options=e.extend({},Z,u,o,d.options,r),d.rules=new n(l.rules,!0),d.messages=new s(l.messages,!0),d.elements=d.elements||{},d.deferred={},d.errors={},d.fields={},d._initFields(l.fields),J(l.groups)&&e.map(l.groups,function(i){return Q(i.fields)&&X(i.callback)?(i.$elems=d.$el.find(a(i.fields)),e.map(i.fields.split(" "),function(e){d.fields[e]=d.fields[e]||{},d.fields[e].group=i}),t):null}),d.msgOpt={type:"error",pos:c(l.msgClass),wrapper:l.msgWrapper,cls:l.msgClass,style:l.msgStyle,icon:l.msgIcon,arrow:l.msgArrow,show:l.msgShow,hide:l.msgHide},d.isAjaxSubmit=!1,l.valid||!e.trim(K(i,"action")))d.isAjaxSubmit=!0;else{var f=e[e._data?"_data":"data"](i,"events");f&&f.valid&&e.map(f.valid,function(e){return-1!==e.namespace.indexOf("form")?1:null}).length&&(d.isAjaxSubmit=!0)}d.$el.data(h)||(d.$el.data(h,d).addClass(k+" "+l.formClass).on("submit"+v+" validate"+v,B(d,"_submit")).on("reset"+v,B(d,"_reset")).on("showtip"+v,B(d,"_showTip")).on("focusin"+v+" click"+v+" showtip"+v,N,B(d,"_focusin")).on("focusout"+v+" validate"+v,N,B(d,"_focusout")),l.timely>=2&&d.$el.on("keyup"+v+" paste"+v,N,B(d,"_focusout")).on("click"+v,":radio,:checkbox",B(d,"_focusout")).on("change"+v,'select,input[type="file"]',B(d,"_focusout")),d._novalidate=K(i,q),K(i,q,q))},_initFields:function(t){var i=this;z(t)&&e.each(t,function(e,t){if(null===t){var n=i.elements[e];n&&i._resetElement(n,!0),delete i.fields[e]}else i.fields[e]=Q(t)?{rule:t}:t}),i.$el.find(N).each(function(){i._parse(this)})},_parse:function(e){var t,i=this,n=e.name,s=K(e,V);s&&K(e,V,null),(e.id&&"#"+e.id in i.fields||!e.name)&&(n="#"+e.id),n&&(t=i.fields[n]||{},t.key=n,t.old={},t.rule=t.rule||s||"",t.rule&&(t.rule.match(/match|checked/)&&(t.must=!0),-1!==t.rule.indexOf("required")&&(t.required=!0,K(e,C,!0)),("timely"in t&&!t.timely||!i.options.timely)&&K(e,"notimely",!0),Q(t.target)&&K(e,S,t.target),Q(t.tip)&&K(e,R,t.tip),i.fields[n]=i._parseRule(t)))},_parseRule:function(e){var i=I.exec(e.rule),n=this.options;if(i)return e._i=0,i[1]&&(e.display=i[1]),!e.display&&n.display&&(e.display=n.display),i[2]&&(e.rules=[],i[2].replace(j,function(){var i=arguments;i[3]=i[3]||i[4],e.rules.push({not:"!"===i[1],method:i[2],params:i[3]?i[3].split(", "):t,or:"|"===i[5]})})),e},_multiValidate:function(i,n){var s=this,r=s.options;return s.verifying=!0,s.isValid=!0,r.ignore&&(i=i.not(r.ignore)),i.each(function(e,i){var n=s.getField(i);return n&&(s._validate(i,n),!s.isValid&&r.stopOnError)?!1:t}),e.when.apply(null,e.map(s.deferred,function(e){return e})).done(function(){n.call(s,s.isValid),s.verifying=!1}),e.isEmptyObject(s.deferred)?s.isValid:t},_submit:function(t){var i=this,n=i.options,s=t.target,r="submit"===t.type;t.preventDefault(),m&&~(m=!1)||i.submiting||"validate"===t.type&&i.$el[0]!==s||n.beforeSubmit.call(i,s)===!1||(n.debug&&Y.log("\n"+t.type),i._reset(),i.submiting=!0,i._multiValidate(i.$el.find(N),function(t){var a,l=t||2===n.debug?"valid":"invalid";t||(n.focusInvalid&&i.$el.find(":input["+F+'="true"]:first').focus(),a=e.map(i.errors,function(e){return e})),i.submiting=!1,X(n[l])&&n[l].call(i,s,a),i.$el.trigger(l+b,[s,a]),t&&!i.isAjaxSubmit&&r&&(m=!0,p&&p.name&&i.$el.append(''),s.submit())}))},_reset:function(e){var t=this;t.errors={},e&&t.$el.find(N).each(function(e,i){t._resetElement(i)})},_resetElement:function(t,i){var n=this.options;e(t).removeClass(n.validClass+" "+n.invalidClass),this.hideMsg(t),i&&K(t,C,null)},_focusin:function(t){var i,n=this,s=n.options,r=t.target;n.verifying||("showtip"!==t.type&&"error"===K(r,E)&&s.focusCleanup&&(e(r).removeClass(s.invalidClass),n.hideMsg(r)),i=K(r,R),i&&n.showMsg(r,{type:"tip",msg:i}))},_focusout:function(t){var i,n,s=this,r=s.options,a=t.target,l=t.type,u={click:1,change:1,paste:1},o=0;if(!u[l]){if("validate"===l)n=!0;else{if(K(a,"notimely"))return;if(r.timely>=2&&"keyup"!==l)return}if(r.ignore&&e(a).is(r.ignore))return;if("keyup"===l){var d=t.keyCode,c={8:1,9:1,16:1,32:1,46:1};if(9===d&&!a.value)return;if(48>d&&!c[d])return;o=r.timely>=100?r.timely:500}}i=s.getField(a),i&&(o?(i._t&&clearTimeout(i._t),i._t=setTimeout(function(){s._validate(a,i,n)},o)):s._validate(a,i,n))},_showTip:function(e){var t=this;t.$el[0]===e.target&&t.$el.find(N+"["+R+"]").each(function(){t.showMsg(this,{msg:K(this,R),type:"tip"})})},_validatedField:function(t,i,n){var s=this,r=s.options,a=n.isValid=i.isValid=!!n.isValid,l=a?"valid":"invalid";n.key=i.key,n.rule=i._r,a?n.type="ok":(s.submiting&&(s.errors[i.key]=n.msg),s.isValid=!1),i.old.value=t.value,i.old.id=t.id,s.elements[i.key]=n.element=t,s.$el[0].isValid=a?s.isFormValid():a,X(i[l])&&i[l].call(s,t,n),e(t).attr(F,a?null:!0).removeClass(a?r.invalidClass:r.validClass).addClass(n.skip?"":a?r.validClass:r.invalidClass).trigger(l+_,[n,s]),s.$el.triggerHandler("validation",[n,s]),s.checkOnly||(i.msgMaker||r.msgMaker)&&s[n.showOk||n.msg?"showMsg":"hideMsg"](t,n,i)},_validatedRule:function(i,n,s,r){n=n||o.getField(i),r=r||{};var a,l,u,o=this,c=o.options,f=n._r,g=!1;if(null===s)return o._validatedField(i,n,{isValid:!0,skip:!0}),t;if(s===!0||s===t||""===s?g=!0:Q(s)?a=s:z(s)&&(s.error?a=s.error:(a=s.ok,g=!0)),n.rules&&(l=n.rules[n._i],l.not&&(a=t,g="required"===f||!g),l.or))if(g)for(;n._i "+(g||r.msg||g)),u||g&&n._i=+l&&+u>=e)return!0;d=d.concat(a)}else if(l&&!u){if(c&&e>=+l)return!0;d.push(l),o="gte"}else if(!l&&u){if(c&&+u>=e)return!0;d.push(u),o="lte"}}else{if(e===+l)return!0;d.push(l),o="eq"}return r&&(n&&r[o+n]&&(o+=n),d[0]=r[o]),s.renderMsg.apply(null,d)}},renderMsg:function(){var e=arguments,t=e[0],i=e.length;if(t){for(;--i;)t=t.replace("{"+i+"}",e[i]);return t}},_getDisplay:function(e,t){return Q(t)?t:X(t)?t.call(this,e):""},_getMsgOpt:function(t){return e.extend({},this.msgOpt,Q(t)?{msg:t}:t)},_getMsgDOM:function(t,i){var n,s,r,a=e(t);if(a.is(":input")?(r=i.target||K(t,S),r&&(r=X(r)?r.call(this,t):this.$el.find(r),r.length&&(r.is(":input")?t=r.get(0):n=r)),n||(s=!f(t)&&t.id?t.id:t.name,n=this.$el.find(i.wrapper+"."+x+'[for="'+s+'"]'))):n=a,!n.length)if(a=this.$el.find(r||t),n=e("<"+i.wrapper+">").attr({"class":x+(i.cls?" "+i.cls:""),style:i.style||"","for":s}),f(t)){var l=a.parent();n.appendTo(l.is("label")?l.parent():l)}else n[i.pos&&"right"!==i.pos?"insertBefore":"insertAfter"](a);return n},showMsg:function(t,i,n){var s,r=this,a=r.options;if(i=r._getMsgOpt(i),(i.msg||i.showOk)&&(t=e(t).get(0),e(t).is(N)&&(K(t,E,i.type),n=n||r.getField(t),n&&(i.style=n.msgStyle||i.style,i.cls=n.msgClass||i.cls,i.wrapper=n.msgWrapper||i.wrapper,i.target=n.target||a.target)),s=(n||{}).msgMaker||a.msgMaker)){var l=r._getMsgDOM(t,i),u=l[0].className;!H.test(u)&&l.addClass(i.cls),G&&"bottom"===i.pos&&(l[0].style.marginTop=e(t).outerHeight()+"px"),l.html(s.call(r,i))[0].style.display="",X(i.show)&&i.show.call(r,l,i.type)}},hideMsg:function(t,i,n){var s=this,r=s.options;t=e(t).get(0),i=s._getMsgOpt(i),e(t).is(N)&&(K(t,E,null),K(t,F,null),n=n||s.getField(t),n&&(i.wrapper=n.msgWrapper||i.wrapper,i.target=n.target||r.target));var a=s._getMsgDOM(t,i);a.length&&(X(i.hide)?i.hide.call(s,a,i.type):a[0].style.display="none")},mapMsg:function(t){var i=this;e.each(t,function(e,t){var n=i.elements[e]||i.$el.find(':input[name="'+e+'"]')[0];i.showMsg(n,t)})},setMsg:function(e){new s(e,this.messages)},setRule:function(t){new n(t,this.rules),e.map(this.fields,function(e){e.old={}})},getField:function(e){var t,i=this;return t=e.id&&"#"+e.id in i.fields||!e.name?"#"+e.id:e.name,K(e,V)&&i._parse(e),i.fields[t]},setField:function(e,t){var i={};Q(e)?i[e]=t:z(e)&&(i=e),this._initFields(i)},isFormValid:function(){var e=this.fields;for(var t in e)if(!e[t].isValid)return e[t].isValid;return!0},holdSubmit:function(e){this.submiting=e===t||e},cleanUp:function(){this._reset(1)},destroy:function(){this._reset(1),this.$el.off(v).removeData(h),K(this.$el[0],q,this._novalidate)}},e(document).on("focusin",":input["+V+"]",function(e){u(e)}).on("click","input,button",function(e){var t=this,i=t.name;if(t.form)if("submit"===t.type)p=t,null!==K(t,q)&&(m=!0);else if(i&&f(t)){var n=t.form.elements[i];n.length&&(n=n[0]),K(n,V)&&u(e)}}).on("submit validate","form",function(t){if(null===K(this,q)){var i,n=e(this);n.data(h)||(i=n[h]().data(h),e.isEmptyObject(i.fields)?(K(this,q,q),n.off(v).removeData(h)):i._submit(t))}}),new n({required:function(t,i){var n=e.trim(t.value),s=!0;if(i)if(1===i.length){if(!n&&!this.test(t,i[0]))return K(t,C,null),null;K(t,C,!0)}else"not"===i[0]&&e.map(i.slice(1),function(t){n===e.trim(t)&&(s=!1)});return s&&!!n},integer:function(e,t){var i,n="0|",s="[1-9]\\d*",r=t?t[0]:"*";switch(r){case"+":i=s;break;case"-":i="-"+s;break;case"+0":i=n+s;break;case"-0":i=n+"-"+s;break;default:i=n+"-?"+s}return i="^(?:"+i+")$",RegExp(i).test(e.value)||this.messages.integer[r]},match:function(t,i,n){if(i){var s,r,a,l,u,o,d,c=this,f="eq";if(1===i.length?a=i[0]:(f=i[0],a=i[1]),u="#"===a.charAt(0)?a:':input[name="'+a+'"]',o=c.$el.find(u)[0]){if(d=c.getField(o),s=t.value,r=o.value,n._match||(c.$el.on("valid"+_+v,u,function(){e(t).trigger("validate")}),n._match=d._match=1),!n.required&&""===s&&""===r)return null;if(i[2]&&("date"===i[2]?(s=g(s),r=g(r)):"time"===i[2]&&(s=+s.replace(":",""),r=+r.replace(":",""))),"eq"!==f&&!isNaN(+s)&&isNaN(+r))return!0;switch(l=c.messages.match[f].replace("{1}",c._getDisplay(t,d.display||a)),f){case"lt":return+r>+s||l;case"lte":return+r>=+s||l;case"gte":return+s>=+r||l;case"gt":return+s>+r||l;case"neq":return s!==r||l;default:return s===r||l}}}},range:function(e,t){return this.getRangeMsg(+e.value,t,"range")},checked:function(t,i,n){if(f(t)){var s,r,a=this;return r=a.$el.find('input[name="'+t.name+'"]').filter(function(){var t=this;return!s&&f(t)&&(s=t),!t.disabled&&t.checked&&e(t).is(":visible")}).length,i?a.getRangeMsg(r,i,"checked"):!!r||d(s,n,"")||a.messages.required}},length:function(e,t){var i=e.value,n=(t[1]?i.replace(U,"xx"):i).length;return this.getRangeMsg(n,t,"length",t[1]?"_2":"")},remote:function(t,i){if(i){var n,s=this,r=L.exec(i[0]),a=r[2],l=(r[1]||"POST").toUpperCase(),u={};return u[t.name]=t.value,i[1]&&e.map(i.slice(1),function(t){var i,n=t.split(":");t=e.trim(n[0]),i=e.trim(n[1]||"")||t,u[t]=s.$el.find("#"===i.charAt(0)?i:':input[name="'+i+'"]').val()}),u=e.param(u),"POST"===l&&(n=a.indexOf("?"),-1!==n&&(u+="&"+a.substring(n+1,a.length),a=a.substring(0,n))),e.ajax({url:a,type:l,data:u,cache:!1})}},filter:function(e,t){e.value=e.value.replace(t?RegExp("["+t[0]+"]","gm"):P,"")}}),i.config=function(t){e.each(t,function(e,t){"rules"===e?new n(t):"messages"===e?new s(t):Z[e]=t})},i.setTheme=function(t,i){z(t)?e.each(t,function(e,t){et[e]=t}):Q(t)&&z(i)&&(et[t]=i)},e[h]=i}(jQuery); diff --git a/static/js/validator/zh_CN.js b/static/js/validator/zh_CN.js new file mode 100644 index 000000000000..ba320330d89b --- /dev/null +++ b/static/js/validator/zh_CN.js @@ -0,0 +1,156 @@ +/********************************* + * Themes, rules, and i18n support + * Locale: Chinese; 中文 + *********************************/ +(function(factory) { + if (typeof define === 'function') { + define(function(require, exports, module){ + var $ = require('jquery'); + $._VALIDATOR_URI = module.uri; + require('../src/jquery.validator')($); + factory($); + }); + } else { + factory(jQuery); + } +}(function($) { + /* Global configuration + */ + $.validator.config({ + //stopOnError: false, + //theme: 'yellow_right', + defaultMsg: "{0}格式不正确", + loadingMsg: "正在验证...", + + // Custom rules + rules: { + digits: [/^\d+$/, "请输入数字"] + ,letters: [/^[a-z]+$/i, "{0}只能输入字母"] + ,tel: [/^(?:(?:0\d{2,3}[\- ]?[1-9]\d{6,7})|(?:[48]00[\- ]?[1-9]\d{6}))$/, "电话格式不正确"] + ,mobile: [/^1[3-9]\d{9}$/, "手机号格式不正确"] + ,email: [/^[\w\+\-]+(\.[\w\+\-]+)*@[a-z\d\-]+(\.[a-z\d\-]+)*\.([a-z]{2,4})$/i, "邮箱格式不正确"] + ,qq: [/^[1-9]\d{4,}$/, "QQ号格式不正确"] + ,date: [/^\d{4}-\d{1,2}-\d{1,2}$/, "请输入正确的日期,例:yyyy-mm-dd"] + ,time: [/^([01]\d|2[0-3])(:[0-5]\d){1,2}$/, "请输入正确的时间,例:14:30或14:30:00"] + ,ID_card: [/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[A-Z])$/, "请输入正确的身份证号码"] + ,url: [/^(https?|ftp):\/\/[^\s]+$/i, "网址格式不正确"] + ,postcode: [/^[1-9]\d{5}$/, "邮政编码格式不正确"] + ,chinese: [/^[\u0391-\uFFE5]+$/, "请输入中文"] + ,username: [/^\w{3,12}$/, "请输入3-12位数字、字母、下划线"] + ,password: [/^[0-9a-zA-Z]{6,16}$/, "密码由6-16位数字、字母组成"] + ,accept: function (element, params){ + if (!params) return true; + var ext = params[0]; + return (ext === '*') || + (new RegExp(".(?:" + (ext || "png|jpg|jpeg|gif") + ")$", "i")).test(element.value) || + this.renderMsg("只接受{1}后缀", ext.replace('|', ',')); + } + + } + }); + + /* Default error messages + */ + $.validator.config({ + messages: { + required: "{0}不能为空", + remote: "{0}已被使用", + integer: { + '*': "请输入整数", + '+': "请输入正整数", + '+0': "请输入正整数或0", + '-': "请输入负整数", + '-0': "请输入负整数或0" + }, + match: { + eq: "{0}与{1}不一致", + neq: "{0}与{1}不能相同", + lt: "{0}必须小于{1}", + gt: "{0}必须大于{1}", + lte: "{0}必须小于或等于{1}", + gte: "{0}必须大于或等于{1}" + }, + range: { + rg: "请输入{1}到{2}的数", + gte: "请输入大于或等于{1}的数", + lte: "请输入小于或等于{1}的数" + }, + checked: { + eq: "请选择{1}项", + rg: "请选择{1}到{2}项", + gte: "请至少选择{1}项", + lte: "请最多选择{1}项" + }, + length: { + eq: "请输入{1}个字符", + rg: "请输入{1}到{2}个字符", + gte: "请至少输入{1}个字符", + lte: "请最多输入{1}个字符", + eq_2: "", + rg_2: "", + gte_2: "", + lte_2: "" + } + } + }); + + /* Themes + */ + var TPL_ARROW = ''; + $.validator.setTheme({ + 'simple_right': { + formClass: 'n-simple', + msgClass: 'n-right' + }, + 'simple_bottom': { + formClass: 'n-simple', + msgClass: 'n-bottom' + }, + 'yellow_top': { + formClass: 'n-yellow', + msgClass: 'n-top', + msgArrow: TPL_ARROW + }, + 'yellow_right': { + formClass: 'n-yellow', + msgClass: 'n-right', + msgArrow: TPL_ARROW + }, + 'yellow_right_effect': { + formClass: 'n-yellow', + msgClass: 'n-right', + msgArrow: TPL_ARROW, + msgShow: function($msgbox, type){ + var $el = $msgbox.children(); + if ($el.is(':animated')) return; + if (type === 'error') { + $el.css({ + left: '20px', + opacity: 0 + }).delay(100).show().stop().animate({ + left: '-4px', + opacity: 1 + }, 150).animate({ + left: '3px' + }, 80).animate({ + left: 0 + }, 80); + } else { + $el.css({ + left: 0, + opacity: 1 + }).fadeIn(200); + } + }, + msgHide: function($msgbox, type){ + var $el = $msgbox.children(); + $el.stop().delay(100).show().animate({ + left: '20px', + opacity: 0 + }, 300, function(){ + $msgbox.hide(); + }); + } + } + }); +})); \ No newline at end of file diff --git a/stopserver b/stopserver deleted file mode 100755 index 45a1452beeec..000000000000 --- a/stopserver +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -pids=$(ps axu | grep -E '(manage.py|log_handler|index.js)' | grep -v 'grep' | awk '{ print $2 }') -for pid in $pids;do - kill -15 $pid -done diff --git a/templates/404.html b/templates/404.html new file mode 100644 index 000000000000..4e4389e5652f --- /dev/null +++ b/templates/404.html @@ -0,0 +1,43 @@ + + + + + + + + + Jumpserver | 404 Error + + + + + + + + + + + + +
+

404

+

Page Not Found

+
+ Sorry, but the page you are looking for has note been found. Try checking the URL for error, then hit the refresh button on your browser or try found something else in our app. +
+
+ +
+ +
+
+
+ + + + + + + + + diff --git a/templates/500.html b/templates/500.html new file mode 100644 index 000000000000..895e3fc18287 --- /dev/null +++ b/templates/500.html @@ -0,0 +1,39 @@ + + + + + + + + + Jumpserver | 500 Error + + + + + + + + + + + + +
+

500

+

Internal Server Error

+ +
+ The server encountered something unexpected that didn't allow it to complete the request. We apologize.
+ You can go back to main page:
Dashboard +
+
+ + + + + + + + + diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 000000000000..729ec6fb7edd --- /dev/null +++ b/templates/base.html @@ -0,0 +1,33 @@ + + + + + + + + + Jumpserver | 开源跳板机系统 + + + {% include 'link_css.html' %} + {% include 'head_script.html' %} + + + + + + +
+ {% include 'nav.html' %} +
+
+ {% include 'nav_bar_header.html' %} +
+ {% block content %}{% endblock %} + {% include 'footer.html' %} +
+
+ + + {% include 'foot_script.html' %} + diff --git a/templates/download.html b/templates/download.html new file mode 100644 index 000000000000..461daf6cf02f --- /dev/null +++ b/templates/download.html @@ -0,0 +1,39 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
下载文件
+ +
+
+

下载文件可联系管理员在服务器安装lrzsz,使用sz命令下载。

+
+
+
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/templates/error.html b/templates/error.html new file mode 100644 index 000000000000..702d7b4b667e --- /dev/null +++ b/templates/error.html @@ -0,0 +1,51 @@ + + + + + + + + + Jumpserver | 500 Error + + + + + + + + + + + + +
+

Error

+

{{ message }}

+

+
+ The server encountered something unexpected that didn't allow it to complete the request. We apologize.
+ You can go back to main page:
首页 +
+
+ + + + + + + + + diff --git a/templates/filter_ajax_api.html b/templates/filter_ajax_api.html new file mode 100644 index 000000000000..0698300a9c24 --- /dev/null +++ b/templates/filter_ajax_api.html @@ -0,0 +1,9 @@ +{% for object in contact_list %} + {% ifequal attr "asset" %} + + {% else %} + + {% endifequal %} + + +{% endfor %} \ No newline at end of file diff --git a/templates/foot_script.html b/templates/foot_script.html new file mode 100644 index 000000000000..df145a91227e --- /dev/null +++ b/templates/foot_script.html @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/footer.html b/templates/footer.html new file mode 100644 index 000000000000..00305471b5e7 --- /dev/null +++ b/templates/footer.html @@ -0,0 +1,8 @@ + diff --git a/templates/head_script.html b/templates/head_script.html new file mode 100644 index 000000000000..ef5f7a1901b4 --- /dev/null +++ b/templates/head_script.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 000000000000..3b831218228c --- /dev/null +++ b/templates/index.html @@ -0,0 +1,408 @@ +{% extends 'base.html' %} +{% load mytags %} +{% load humanize %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+ Users +
用户总数
+
+
+

{{ users.count}}

+
{{ percent_user }}
+ All user +
+
+
+
+
+
+ Hosts +
主机总数
+
+
+

{{ hosts.count }}

+
{{ percent_host }}
+ All host +
+
+
+ +
+
+
+ Online +
实时在线用户
+
+
+

+
{{ percent_online_user }}
+ Online user +
+
+
+ +
+
+
+ Connected +
已连接服务器
+
+
+

+
{{ percent_online_host }}
+ Connected host +
+
+
+
+
+
+

活跃用户TOP5

+ 过去一周共有{{ week_users }}位用户登录{{ week_hosts }}次服务器. +
    + {% for data in user_top_five %} +
  • + + {{ data.times }}次/周 + + {{ forloop.counter }} {{ data.user }} +
  • + {% endfor %} +
+
+
+
+
+ +
+
+
+
+
权限申请
+ +
+
+

权限申请记录

+ 最近十条权限申请记录信息. +
+
+
+ {% if perm_apply_10 %} + {% for perm in perm_apply_10 %} +
+
+ {% ifequal perm.status 0 %} + {{ perm.date_add|naturaltime }} + {% else %} + {{ perm.date_add|naturaltime }} + {% endifequal %} + {{ perm.applyer }} +
申请 {{ perm.bisgroup|ast_to_list }} 主机组权限
+
申请 {{ perm.asset|ast_to_list }} 主机权限
+ {{ perm.date_add }} +
+
+ {% endfor %} + {% else %} +

(暂无)

+ {% endif %} +
+
+
+
+
+
+
+
最近十次登录
+
+ 10 Messages +
+
+
+

登录记录

+ 最近十次登录记录. +
+
+
+
+ {% if login_10 %} + {% for login in login_10 %} +
+ + image + +
+ {% ifequal login.is_finished 0 %} + {{ login.start_time|naturaltime }} + {% else %} + {{ login.start_time|naturaltime }} + {% endifequal %} + {{ login.user }} 登录了{{ login.host }}
+ {{ login.start_time }} + +
+
+ {% endfor %} + + + + {% else %} +

(暂无)

+ {% endif %} +
+
+
+
+
+ +
+
+
+
一周Top10用户
+ +
+
+

一周Top10用户

+ 一周Top10用户登录次数及最近一次登录记录. +
+
+ {% if user_top_ten %} + {% for data in user_top_ten %} +
+
+
+ + {{ data.user }} +
+ {{ data.times }}次 +
+
+

最近一次登录

+

{{ data.last.host }}

+

于{{ data.last.start_time |date:"Y-m-d H:i:s" }}

+
+
+
+ {% endfor %} + {% else %} +

(暂无)

+ {% endif %} +
+
+
+ + + + + + + +
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/index_cu.html b/templates/index_cu.html new file mode 100644 index 000000000000..116613fab620 --- /dev/null +++ b/templates/index_cu.html @@ -0,0 +1,162 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
使用说明
+ +
+ +
+ 迎使用Jumpserver跳板机系统, + 首先需要 下载 登录跳板机的SSH密钥文件,然后导入到工具或者ssh命令指定密钥文件(确保密钥文件权限600),输入收到的密钥密码,登录跳板机。 + 登录后根据提示进行操作。跳板机web界面支持修改密码、个人信息和上传下载文件等功能,可以向管理员申请权限。 +
+
+ +
+
+
已授权主机
+
+
总共:{{ host_count }}
+ + + + + + + + + + +
+
+ +
+ + {% for host_five in new_posts %} + + {% for host in host_five %} + + {% endfor %} + + {% endfor %} +
{{ host.ip }}
+ {% ifequal host_count 0 %} + (空) + {% endifequal %} +
+
+
+ +
+
+
+ {{ user.name }} +
+ + + + + + + + + + +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ID{{ user.id }}
用户名{{ user.username }}
姓名{{ user.name }}
角色{{ user.id | get_role }}
部门{{ user.dept.name }}
Email{{ user.email }}
激活{{ user.is_active|bool2str }}
添加日期{{ user.date_joined|date:"Y-m-d H:i:s" }}
最后登录{{ user.last_login|date:"Y-m-d H:i:s" }}
所在用户组 + + {% for group in user.group.all %} + + + + {% endfor %} +
{{ group.name }}
+
+
+
+
+
+
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/templates/jasset/dept_host_ajax.html b/templates/jasset/dept_host_ajax.html new file mode 100644 index 000000000000..be529cfc74a1 --- /dev/null +++ b/templates/jasset/dept_host_ajax.html @@ -0,0 +1,3 @@ +{% for host in hosts %} + +{% endfor %} \ No newline at end of file diff --git a/templates/jasset/group_add.html b/templates/jasset/group_add.html new file mode 100644 index 000000000000..be6c7b91d8e4 --- /dev/null +++ b/templates/jasset/group_add.html @@ -0,0 +1,206 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + + +
+
+
+
+
+
填写主机组基本信息
+ +
+ + + + + +
+ {% if emg %} +
{{ emg }}
+ {% endif %} + {% if smg %} +
{{ smg }}
+ {% endif %} +
+
+
+
+ + {% ifequal session_role_id 2 %} +
+
+ +
+ +
+
+ {% endifequal %} + + {% ifequal session_role_id 1 %} +
+
+ + +
+
+ {% endifequal %} + +
+
+ +
+ +
+
+
+
+ +
+
+ + +
+ +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+
+ +
+
+
+
+ +
+
+
+ + +
+
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/jasset/group_detail.html b/templates/jasset/group_detail.html new file mode 100644 index 000000000000..0f31d3cf68e8 --- /dev/null +++ b/templates/jasset/group_detail.html @@ -0,0 +1,203 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
主机组{{ group.name }}详细信息列表
+ +
+ +
+
+ 添加主机 + 提示: 此页面删除只从本主机组中剔除主机 +
+ +
+ + + + + + + + + + + + + + + + + {% for post in contacts.object_list %} + + + + + + + + + + + + + {% endfor %} + +
IP地址 端口号 登录方式 所属IDC 所属业务组 是否激活 添加时间 备注 操作
{{ post.ip }} {{ post.port }} {{ post.login_type|get_login_type }} {{ post.idc.name }} {{ post.bis_group.all | group_str2 }} {{ post.is_active|bool2str }} {{ post.date_added|date:"Y-m-d H:i:s" }} {{ post.comment }} + 详情 + 编辑 + 删除 +
+
+
+ + +
+
+
+
    + {% if keyword %} + {% if contacts.has_previous %} + + {% else %} + + {% endif %} + {% ifequal show_first 1 %} +
  • 1...
  • + {% endifequal %} + {% for page in page_range %} + {% ifequal current_page page %} +
  • {{ page }}
  • + {% else %} +
  • {{ page }}
  • + {% endifequal %} + {% endfor %} + {% ifequal show_end 1 %} +
  • ...{{ p.num_pages }}
  • + {% endifequal %} + {% if contacts.has_next %} + + {% else %} + + {% endif %} + + {% else %} + {% if contacts.has_previous %} + + {% else %} + + {% endif %} + {% ifequal show_first 1 %} +
  • 1...
  • + {% endifequal %} + {% for page in page_range %} + {% ifequal current_page page %} +
  • {{ page }}
  • + {% else %} +
  • {{ page }}
  • + {% endifequal %} + {% endfor %} + {% ifequal show_end 1 %} +
  • ...{{ p.num_pages }}
  • + {% endifequal %} + {% if contacts.has_next %} + + {% else %} + + {% endif %} + {% endif %} +
+
+
+
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/jasset/group_edit.html b/templates/jasset/group_edit.html new file mode 100644 index 000000000000..2f142a2e38b8 --- /dev/null +++ b/templates/jasset/group_edit.html @@ -0,0 +1,174 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + + +
+
+
+
+
+
填写主机组基本信息
+ +
+ + + + + +
+ {% if emg %} +
{{ emg }}
+ {% endif %} + {% if smg %} +
{{ smg }}
+ {% endif %} +
+
+
+
+ +
+
+ + +
+
+ +
+
+ +
+ +
+
+
+
+ +
+
+ + +
+ +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+
+ +
+
+
+
+ +
+
+
+ + +
+
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/jasset/group_list.html b/templates/jasset/group_list.html new file mode 100644 index 000000000000..b171df3820fa --- /dev/null +++ b/templates/jasset/group_list.html @@ -0,0 +1,117 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
主机组详细信息列表
+ +
+
+
+ 添加主机组 + +
+ +
+ + + + + + + + + + + + + {% for post in contacts.object_list %} + + + + + {% ifequal session_role_id 2 %} + + {% else %} + + {% endifequal %} + + + + {% endfor %} + +
主机组名 所属部门 主机数量 备注 操作
{{ post.name }} {{ post.dept.name }} {{ post.asset_set.count }} {{ post|get_group_count:dept }} {{ post.comment }} + 详情 + 编辑 + 删除 +
+
+
+ + +
+ {% include 'paginator.html' %} +
+
+
+
+
+
+
+ + + +{% endblock %} diff --git a/templates/jasset/host_add.html b/templates/jasset/host_add.html new file mode 100644 index 000000000000..bbfa730b5740 --- /dev/null +++ b/templates/jasset/host_add.html @@ -0,0 +1,207 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} +
+
+
+
+
+
填写主机基本信息
+ +
+ +
+
+ +
+
+
+ {% if emg %} +
{{ emg }}
+ {% endif %} + {% if smg %} +
{{ smg }}
+ {% endif %} +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+ + +
+ +
+
+ +
+ +
+
+ + {% ifequal session_role_id 2 %} +
+
+ +
+ +
+
+ {% endifequal %} + + {% ifequal session_role_id 1 %} +
+
+ +
+
+ {% endifequal %} + +
+
+ +
+ +
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/jasset/host_add_multi.html b/templates/jasset/host_add_multi.html new file mode 100644 index 000000000000..122ca2ec3997 --- /dev/null +++ b/templates/jasset/host_add_multi.html @@ -0,0 +1,68 @@ +{% extends 'base.html' %} +{% block content %} +{% include 'nav_cat_bar.html' %} +
+
+
+
+
+
填写主机基本信息
+ +
+ +
+
+ +
+
+ {% if emg %} +
{{ emg }}
+ {% endif %} + {% if smg %} +
{{ smg }}
+ {% endif %} +

请严格按照文本框内主机信息格式填写, 多台主机回车换行, 具体格式如下:

+

IP地址 端口号 登录方式 IDC名 所属主机组 所属部门 激活/禁用 备注

+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/templates/jasset/host_detail.html b/templates/jasset/host_detail.html new file mode 100644 index 000000000000..399fe52501c1 --- /dev/null +++ b/templates/jasset/host_detail.html @@ -0,0 +1,221 @@ +{% extends 'base.html' %} +{% load mytags %} + + +{% block content %} + {% include 'nav_cat_bar.html' %} +
+
+
+
+
+ {{ post.ip }} +
+ + + + + + + + + + +
+
+
+

主机详细信息

+ 此主机详细信息. +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IP{{ post.ip }}
端口{{ post.port }}
登录方式{{ post.login_type|get_login_type }}
IDC{{ post.idc.name }}
部门 + + {% for dept in post.dept.all %} + + + + {% endfor %} +
{{ dept.name }}
+
主机组 + + {% for group in post.bis_group.all %} + + + + {% endfor %} +
{{ group.name }}
+
激活{{ post.is_active|bool2str }}
添加日期{{ post.date_added|date:"Y-m-d H:i:s" }}
备注{{ post.comment }}
+
+
+
+
+
+
+
+
+
拥有权限的用户
+
+ + + + + + + + + + +
+
+
+

主机所有授权的用户

+ 包含了此主机所有授权的用户. +
+
+
+
+ + {% if user_permed_list %} + {% for user in user_permed_list %} + + + + + + {% endfor %} + {% else %} +

(暂无)

+ {% endif %} +
{{ user.name }}{{ user.dept.name }}详情
+
+
+
+
+
+ +
+
+
+
最近一周登录记录
+
+ + + + + + + + + + +
+
+
+

最近一周登录记录

+ 此主机最近一周用户登录信息. +
+
+ {% if log %} + {% for l in log %} +
+
+
+ + {{ l.user }} +
+ {{l.dept_name}} +
+
+

详细信息

+

来源IP: {{ l.remote_ip }}

+

开始: {{ l.start_time |date:"Y-m-d H:i:s" }}

+

结束: {{ l.end_time |date:"Y-m-d H:i:s" }}

+
+
+
+ {% endfor %} + + +
+
+
+
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/jasset/host_edit.html b/templates/jasset/host_edit.html new file mode 100644 index 000000000000..f568a92c1754 --- /dev/null +++ b/templates/jasset/host_edit.html @@ -0,0 +1,228 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} +
+
+
+
+
+
填写主机基本信息
+ +
+ +
+ {% if emg %} +
{{ emg }}
+ {% endif %} + {% if smg %} +
{{ smg }}
+ {% endif %} +
+
+
+
+ +
+
+
+
+ +
+
+
+ {% for t, type in login_types.items %} + {% ifequal t post.login_type %} +
+ {% else %} +
+ {% endifequal %} + {% endfor %} +
+ + {% ifequal post.login_type 'M' %} +
+
+
+
+ +
+
+
+
+ {% endifequal %} +
+ +
+
+ +
+ +
+
+ + {% ifequal session_role_id 2 %} +
+
+ +
+ +
+
+ {% endifequal %} + + {% ifequal session_role_id 1 %} +
+
+ +
+
+ {% endifequal %} + +
+
+ +
+ +
+
+ +
+
+
+ {% for a,active in actives.items %} + {% ifequal a post.is_active %} +
+ {% else %} +
+ {% endifequal %} + {% endfor %} +
+
+ +
+
+
+
+ +
+
+
+ + +
+
+
+
+
+
+
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/jasset/host_list.html b/templates/jasset/host_list.html new file mode 100644 index 000000000000..8617e295831a --- /dev/null +++ b/templates/jasset/host_list.html @@ -0,0 +1,192 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
主机详细信息列表
+ +
+ +
+
+ 添加 + +
+ +
+ + + + + + + + + + + + + + + + + {% for post in contacts.object_list %} + + + + + + + + + + + + + + + {% endfor %} + +
IP地址 端口号 登录方式 所属IDC 所属部门 所属主机组 是否激活 备注 操作
{{ post.ip }} {{ post.port }} {{ post.login_type|get_login_type }} {{ post.idc.name }} {{ post.dept.all | group_str2 }}{{ post.bis_group.all | group_str2_all }} {{ post.is_active|bool2str }} {{ post.comment }} + 详情 + {% ifnotequal session_role_id 0 %} + 编辑 + 删除 + {% endifnotequal %} +
+
+
+ + +
+ {% include 'paginator.html' %} +
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/jasset/host_list_common.html b/templates/jasset/host_list_common.html new file mode 100644 index 000000000000..3ea78f019d17 --- /dev/null +++ b/templates/jasset/host_list_common.html @@ -0,0 +1,172 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
主机详细信息列表
+ +
+ +
+
+ 点击别名栏修改主机别名, 可在跳板机上使用别名直接登录. + +
+ +
+ + + + + + + + + + + + + + + + + {% for post in contacts.object_list %} + + + + + + + + + + + + + {% endfor %} + +
IP地址 端口号 登录方式 所属IDC 所属部门 所属主机组 别名 备注 操作
{{ post.ip }} {{ post.port }} {{ post.login_type|get_login_type }} {{ post.idc.name }} {{ post.dept.all | group_str2 }}{{ post.bis_group.all | group_str2_all }} {{ post|get_user_alias:user_id }} {{ post.comment }} + 详情 +
+
+
+ +
+ {% include 'paginator.html' %} +
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/jasset/host_list_nop.html b/templates/jasset/host_list_nop.html new file mode 100644 index 000000000000..eb1e3dd34bd2 --- /dev/null +++ b/templates/jasset/host_list_nop.html @@ -0,0 +1,177 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
主机详细信息列表
+ +
+ +
+
+ 添加 + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + {% for post in posts %} + + + + + + + + + + + + + {% endfor %} + +
IP地址 端口号 登录方式 所属IDC 所属部门 所属主机组 是否激活 备注 操作
{{ post.ip }} {{ post.port }} {{ post.login_type|get_login_type }} {{ post.idc.name }} {{ post.dept.all | group_str2 }}{{ post.bis_group.all | group_str2_all }} {{ post.is_active|bool2str }} {{ post.comment }} + 详情 + {% ifnotequal session_role_id 0 %} + 编辑 + 删除 + {% endifnotequal %} +
+
+
+ + +
+ +
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/jasset/host_search.html b/templates/jasset/host_search.html new file mode 100644 index 000000000000..38ed8c1add5f --- /dev/null +++ b/templates/jasset/host_search.html @@ -0,0 +1,169 @@ +{% load mytags %} + + + + + + + + + + {% ifnotequal session_role_id 0 %} + + {% else %} + + {% endifnotequal %} + + + + + + + {% for post in contacts.object_list %} + + + + + + + + {% ifnotequal session_role_id 0 %} + + {% else %} + + {% endifnotequal %} + + + + + {% endfor %} + +
IP地址 端口号 登录方式 所属IDC 所属业务组 是否激活 别名 添加时间 备注 操作
{{ post.ip }} {{ post.port }} {{ post.login_type|get_login_type }} {{ post.idc.name }} {{ post.bis_group.all | group_str2 }} {{ post.is_active|bool2str }} {{ post|get_user_alias:user_id }} {{ post.date_added|date:"Y-m-d H:i:s" }} {{ post.comment }} + 详情 + {% ifnotequal session_role_id 0 %} + 编辑 + 删除 + {% endifnotequal %} +
+
+
+ + +
+
+
+
    + + {% if contacts.has_previous %} + + {% else %} + + {% endif %} + {% ifequal show_first 1 %} +
  • 1...
  • + {% endifequal %} + {% for page in page_range %} + {% ifequal current_page page %} +
  • {{ page }}
  • + {% else %} +
  • {{ page }}
  • + {% endifequal %} + {% endfor %} + {% ifequal show_end 1 %} +
  • ...{{ p.num_pages }}
  • + {% endifequal %} + {% if contacts.has_next %} + + {% else %} + + {% endif %} +
+
+
+ +
+ + diff --git a/templates/jasset/idc_add.html b/templates/jasset/idc_add.html new file mode 100644 index 000000000000..5c184e7e2296 --- /dev/null +++ b/templates/jasset/idc_add.html @@ -0,0 +1,79 @@ +{% extends 'base.html' %} +{% block content %} +{% include 'nav_cat_bar.html' %} +
+
+
+
+
+
填写IDC基本信息
+ +
+ +
+ {% if emg %} +
{{ emg }}
+ {% endif %} + {% if smg %} +
{{ smg }}
+ {% endif %} +
+
+
+
+ +
+
+
+
+ +
+
+
+ + +
+
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/jasset/idc_detail.html b/templates/jasset/idc_detail.html new file mode 100644 index 000000000000..acc072590b18 --- /dev/null +++ b/templates/jasset/idc_detail.html @@ -0,0 +1,211 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
IDC {{ idc.name }} 详细信息列表
+ +
+ +
+ {% if emg %} +
{{ emg }}
+ {% endif %} + {% if smg %} +
{{ smg }}
+ {% endif %} + + +
+ + + + + + + + + + + + + + + + + {% for post in contacts.object_list %} + + + + + + + + + + + + + {% endfor %} + +
IP地址 端口号 登录方式 所属IDC 所属业务组 是否激活 添加时间 备注 操作
{{ post.ip }} {{ post.port }} {{ post.login_type|get_login_type }} {{ post.idc.name }} {{ post.dept.all | group_str2 }}{{ post.bis_group.all | group_str2_all }} {{ post.is_active|bool2str }} {{ post.comment }} + 详情 + {% ifnotequal session_role_id 0 %} + 编辑 + 删除 + {% endifnotequal %} +
+
+
+ + +
+
+
+
    + {% if keyword %} + {% if contacts.has_previous %} + + {% else %} + + {% endif %} + {% ifequal show_first 1 %} +
  • 1...
  • + {% endifequal %} + {% for page in page_range %} + {% ifequal current_page page %} +
  • {{ page }}
  • + {% else %} +
  • {{ page }}
  • + {% endifequal %} + {% endfor %} + {% ifequal show_end 1 %} +
  • ...{{ p.num_pages }}
  • + {% endifequal %} + {% if contacts.has_next %} + + {% else %} + + {% endif %} + + {% else %} + {% if contacts.has_previous %} + + {% else %} + + {% endif %} + {% ifequal show_first 1 %} +
  • 1...
  • + {% endifequal %} + {% for page in page_range %} + {% ifequal current_page page %} +
  • {{ page }}
  • + {% else %} +
  • {{ page }}
  • + {% endifequal %} + {% endfor %} + {% ifequal show_end 1 %} +
  • ...{{ p.num_pages }}
  • + {% endifequal %} + {% if contacts.has_next %} + + {% else %} + + {% endif %} + {% endif %} +
+
+
+
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/jasset/idc_edit.html b/templates/jasset/idc_edit.html new file mode 100644 index 000000000000..0751a4114165 --- /dev/null +++ b/templates/jasset/idc_edit.html @@ -0,0 +1,109 @@ +{% extends 'base.html' %} +{% block content %} +{% include 'nav_cat_bar.html' %} +
+
+
+
+
+
填写IDC基本信息
+ +
+ +
+ {% if emg %} +
{{ emg }}
+ {% endif %} + {% if smg %} +
{{ smg }}
+ {% endif %} +
+
+
+ + +
+
+ +
+
+
+
+ +
+
+ +
+ +
+
+
+ + +
+
+
+
+ +
+
+
+ +
+
+
+ + +
+
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/jasset/idc_list.html b/templates/jasset/idc_list.html new file mode 100644 index 000000000000..e1f5dd465108 --- /dev/null +++ b/templates/jasset/idc_list.html @@ -0,0 +1,125 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
IDC详细信息列表
+ +
+
+
+ {% ifequal session_role_id 2 %} + 添加IDC + {% endifequal %} + +
+ +
+ + + + {% ifequal session_role_id 2 %} + + {% endifequal %} + + + + + + + + {% for post in contacts.object_list %} + + {% ifequal session_role_id 2 %} + + {% endifequal %} + + {% ifequal session_role_id 2 %} + + {% else %} + + {% endifequal %} + + + + {% endfor %} + +
机房名 主机数量 备注 操作
{{ post.name }} {{ post.asset_set.count }} {{ post|get_idc_count:dept }} {{ post.comment }} + 详情 + {% ifequal session_role_id 2 %} + 编辑 + 删除 + {% endifequal %} +
+
+
+ {% ifequal session_role_id 2 %} + + + {% endifequal %} +
+ {% include 'paginator.html' %} +
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/jasset/jasset.html b/templates/jasset/jasset.html new file mode 100644 index 000000000000..e92bd8eddda1 --- /dev/null +++ b/templates/jasset/jasset.html @@ -0,0 +1,10 @@ + + + + + 资产管理 + + +

welocome!

+ + \ No newline at end of file diff --git a/templates/jasset/jlist_ip.html b/templates/jasset/jlist_ip.html new file mode 100644 index 000000000000..f41dd01c8bfe --- /dev/null +++ b/templates/jasset/jlist_ip.html @@ -0,0 +1,106 @@ +{% load mytags %} + + + {% include 'link_css.html' %} + {% include 'head_script.html' %} + + + + + +
+
+

{{ offset }}主机详情

+ + + + + + + + + + + + + + + + + + + + + + + +
IP地址 端口号 登录方式 所属IDC 所属业务组 添加时间 备注
{{ post.ip }} {{ post.port }} {{ post.login_type|get_login_type }} {{ post.idc.name }} {% for group in post.bis_group.all %} {{ group }} {% endfor %} {{ post.date_added|date:"Y-m-d H:i:s" }} {{ post.comment }}
+

{{ offset }}主机用户权限详情

+ + + + + + + + + + + +
用户名
+ {% for user in user_permed_list %} + {{ user.name }} + {% endfor %} +
+ +

最近一周登录详情

+ + + + + + + + + + + {% for l in log %} + + + + + + + {% endfor %} + +
用户名 登录时间 退出时间 详情
{{ l.user }} {{ l.start_time|date:"Y-m-d H:i:s" }} {{ l.end_time|date:"Y-m-d H:i:s" }} + 命令统计 +
+
+
+ + + + + \ No newline at end of file diff --git a/templates/jasset/show_all_ajax.html b/templates/jasset/show_all_ajax.html new file mode 100644 index 000000000000..c26b405cb7e2 --- /dev/null +++ b/templates/jasset/show_all_ajax.html @@ -0,0 +1,7 @@ +{% load mytags %} +{% ifequal env 'group' %} + {{ host.bis_group.all|group_dept_all }} +{% endifequal %} +{% ifequal env 'dept' %} + {{ host.dept.all|group_dept_all }} +{% endifequal %} \ No newline at end of file diff --git a/templates/jasset/test.html b/templates/jasset/test.html new file mode 100644 index 000000000000..6ece5b502e09 --- /dev/null +++ b/templates/jasset/test.html @@ -0,0 +1,30 @@ + + \ No newline at end of file diff --git a/templates/jlog/log_offline.html b/templates/jlog/log_offline.html new file mode 100644 index 000000000000..30d4511eb983 --- /dev/null +++ b/templates/jlog/log_offline.html @@ -0,0 +1,159 @@ +{% extends 'base.html' %} +{% block content %} +{% include 'nav_cat_bar.html' %} + + +
+
+
+
+
+
用户日志详细信息列表
+ +
+ +
+
+ +
+
+
+ + + + + + + + {% ifnotequal session_role_id 0 %} + + {% endifnotequal %} + + + + + + + {% for post in contacts.object_list %} + + + + + + {% ifnotequal session_role_id 0 %} + + {% endifnotequal %} + + + + {% endfor %} + +
用户名 所属部门 登录主机 来源IP 命令统计 登录时间 结束时间
{{ post.user }} {{ post.dept_name }} {{ post.host }} {{ post.remote_ip }} 命令统计 {{ post.start_time|date:"Y-m-d H:i:s"}} {{ post.end_time|date:"Y-m-d H:i:s" }}
+
+
+
+ {% include 'paginator.html' %} +
+
+
+
+
+
+
+ + +{##} + +{% endblock %} \ No newline at end of file diff --git a/templates/jlog/log_online.html b/templates/jlog/log_online.html new file mode 100644 index 000000000000..2ae318d88c9d --- /dev/null +++ b/templates/jlog/log_online.html @@ -0,0 +1,218 @@ +{% extends 'base.html' %} +{% block content %} +{% include 'nav_cat_bar.html' %} + + +
+
+
+
+
+
用户日志详细信息列表
+ +
+ +
+
+ +
+
+
+ + + + + + + + {% ifnotequal session_role_id 0 %} + + + {% endifnotequal %} + + + + + + {% for post in contacts.object_list %} + + + + + + {% ifnotequal session_role_id 0 %} + + + {% endifnotequal %} + + + {% endfor %} + +
用户名 所属部门 登录主机 来源IP 实时监控 阻断 登录时间
{{ post.user }} {{ post.dept_name }} {{ post.host }} {{ post.remote_ip }} 监控 {{ post.start_time|date:"Y-m-d H:i:s" }}
+
+
+ {% include 'paginator.html' %} +
+
+
+
+
+
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/jlog/log_search.html b/templates/jlog/log_search.html new file mode 100644 index 000000000000..e3698b6a4107 --- /dev/null +++ b/templates/jlog/log_search.html @@ -0,0 +1,33 @@ +
+ + + + + + + + + + + + + + + {% for post in contacts.object_list %} + + + + + + + + + + {% endfor %} + +
用户名 所属部门 登录主机 来源IP 命令统计 登录时间 结束时间
{{ post.user }} {{ post.dept_name }} {{ post.host }} {{ post.remote_ip }} 命令统计 {{ post.start_time|date:"Y-m-d H:i:s"}} {{ post.end_time|date:"Y-m-d H:i:s" }}
+
+
+ {% include 'paginator.html' %} +
+
\ No newline at end of file diff --git a/templates/jlog/user_history.html b/templates/jlog/user_history.html new file mode 100644 index 000000000000..4e166b52e5ac --- /dev/null +++ b/templates/jlog/user_history.html @@ -0,0 +1,163 @@ +{% extends 'base.html' %} +{% block content %} +{% include 'nav_cat_bar.html' %} + + +
+
+
+
+
+
用户{{ username }}日志详细信息列表
+ +
+ +
+
+ +
+
+
+ + + + + + + + + + + + + + + {% for post in contacts.object_list %} + + + + + + + + + + {% endfor %} + +
用户名 所属部门 登录主机 来源IP 登录时间 结束时间
{{ post.user }} {{ post.dept_name }} {{ post.host }} {{ post.remote_ip }} {{ post.start_time|date:"Y-m-d H:i:s"}} {{ post.end_time|date:"Y-m-d H:i:s" }}
+
+
+
+ {% include 'paginator.html' %} +
+
+
+
+
+
+
+ + +{##} + +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/dept_perm_edit.html b/templates/jperm/dept_perm_edit.html new file mode 100644 index 000000000000..7d9c8247f8fe --- /dev/null +++ b/templates/jperm/dept_perm_edit.html @@ -0,0 +1,179 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + + +
+
+
+
+
+
部门授权编辑
+ +
+ + + + + +
+
+ {% if error %} +
{{ error }}
+ {% endif %} + {% if msg %} +
{{ msg }}
+ {% endif %} +
+
+ +
+ + +
+
+ +
+ +
+ +
+ +
+
+
+
+ +
+
+ + +
+ +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+
+
+ +
+
+
+ + +
+
+
+
+ +
+
+
+
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/dept_perm_list.html b/templates/jperm/dept_perm_list.html new file mode 100644 index 000000000000..92d467d89715 --- /dev/null +++ b/templates/jperm/dept_perm_list.html @@ -0,0 +1,104 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
查看部门
+ +
+ +
+
+ 添加部门 + +
+ + + + + + + + + + + + + + {% for dept in contacts.object_list %} + + + + + + + + {% endfor %} + +
部门名称部门成员数目授权主机数目备注操作
{{ dept.name }} {{ dept.id | dept_user_num }} {{ dept.id | dept_asset_num }} {{ dept.comment }} +{# 主机#} + 授权编辑 +
+
+
+
+ Showing {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries +
+
+ {% include 'paginator.html' %} +
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/perm_add.html b/templates/jperm/perm_add.html new file mode 100644 index 000000000000..727d45d0305d --- /dev/null +++ b/templates/jperm/perm_add.html @@ -0,0 +1,176 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
主机授权添加
+ +
+ +
+
+ {% if error %} +
{{ error }}
+ {% endif %} + {% if msg %} +
{{ msg }}
+ {% endif %} +
+
+ +
+ + 取个名字方便辨识 +
+
+
+ +
+ +
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+ +
+
+
+ +
+ +
+ +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+
+ +
+
+ +
+ +
+
+
+
+ +
+
+
+ + +
+
+
+
+ +
+
+
+
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/perm_apply.html b/templates/jperm/perm_apply.html new file mode 100644 index 000000000000..167a9574ebf5 --- /dev/null +++ b/templates/jperm/perm_apply.html @@ -0,0 +1,187 @@ +{% extends 'base.html' %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
填写要申请主机的基本信息
+
+ + + + + + + + + + +
+
+ + + + + +
+ {% if emg %} +
{{ emg }}
+ {% endif %} + {% if smg %} +
{{ smg }}
+ {% endif %} +
+ {% csrf_token %} +
+
+
+ +
+
+
+
+ +
+
+
+ + {% for da in dept_da %} + + {% endfor %} +
+
+ +
+
+ +
+ +
+
+ +
+
+ +
+ +
+
+
+
+ +
+
+ + +
+ +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+
+ + +
+
+
+
+ +
+
+
+ +
+
+
+
+
+
+
+
+ + +{% endblock content %} \ No newline at end of file diff --git a/templates/jperm/perm_apply_exec.html b/templates/jperm/perm_apply_exec.html new file mode 100644 index 000000000000..6e95802105ed --- /dev/null +++ b/templates/jperm/perm_apply_exec.html @@ -0,0 +1,31 @@ +{% extends 'base.html' %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+

+
+
+
+
+
+ + + +{% endblock content %} \ No newline at end of file diff --git a/templates/jperm/perm_apply_info.html b/templates/jperm/perm_apply_info.html new file mode 100644 index 000000000000..716b76f154d1 --- /dev/null +++ b/templates/jperm/perm_apply_info.html @@ -0,0 +1,55 @@ +{% load mytags %} + + + + + + + + + + + + + + +
+

{{ post.applyer }}权限申请详情

+
+
+
+
申请人
+
所属部门
+
申请主机组
+
申请主机
+ {% for i in post.asset|ast_to_list_1 %} +
Null
+ {% endfor %} +
批准人
+
申请时间
+
批准时间
+
备注
+
+
+
+
+
+
{{ post.applyer }}
+
{{ post.dept }}
+
{% for i in post.bisgroup|ast_to_list_1 %} {{ i }} {% endfor %}
+ {% for i in post.asset|ast_to_list_1 %} +
{{ i }}
+ {% endfor %} +
Null
+
{{ post.approver }}1
+
{{ post.date_add|date:"Y-m-d H:i:s"}}
+
{{ post.date_end|date:"Y-m-d H:i:s" }}1
+
{{ post.comment }}
+
+
+
+ + \ No newline at end of file diff --git a/templates/jperm/perm_apply_search.html b/templates/jperm/perm_apply_search.html new file mode 100644 index 000000000000..7f62da3aaa66 --- /dev/null +++ b/templates/jperm/perm_apply_search.html @@ -0,0 +1,40 @@ +{% load mytags %} +
+ + + + + + + + + + + + + + + + {% for post in contacts.object_list %} + + + + + + + + + + + {% endfor %} + +
申请人 所属部门 申请主机组 申请主机 批准人 申请时间 备注 详情
{{ post.applyer }} {{ post.dept }} {{ post.bisgroup|ast_to_list }} {{ post.asset|ast_to_list }} {{ post.approver }} {{ post.date_add|date:"Y-m-d H:i:s"}} {{ post.comment }} + 详情 +
+
+
+
+ {% include 'paginator.html' %} +
+
+
\ No newline at end of file diff --git a/templates/jperm/perm_asset_detail.html b/templates/jperm/perm_asset_detail.html new file mode 100644 index 000000000000..8be1ece6b5a5 --- /dev/null +++ b/templates/jperm/perm_asset_detail.html @@ -0,0 +1,61 @@ +{% extends 'base.html' %} +{% load mytags %} + +{% block content %} + {% include 'nav_cat_bar.html' %} +
+
+ +
+
+
+
授权主机详情
+ +
+
+ + + + + + + + + + {% for asset in assets_list %} + + + + + + {% endfor %} + +
IPIDC主机组
{{ asset.ip }}{{ asset.idc.name }} + {% for group in asset.bis_group.all|filter_private %} + {{ group }} + {% endfor %} +
+
+
+
+ +
+
+ +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/perm_detail.html b/templates/jperm/perm_detail.html new file mode 100644 index 000000000000..b772e4613b00 --- /dev/null +++ b/templates/jperm/perm_detail.html @@ -0,0 +1,118 @@ +{% extends 'base.html' %} +{% load mytags %} + +{% block content %} + {% include 'nav_cat_bar.html' %} +
+
+
+
+
+
授权主机/组
+ +
+
+

用户

+ 组下用户. +
+
+
+
+
+ + {{ user_group.name }} +
+ 共: {{ group_user_num }} 用户 +
+
+

{{ user_group.comment }}

+

+ {% for user in users %} + {{ user.name }}
+ {% endfor %} +

+

+
+
+
+ {% if not user|get_user_asset_group %} + (无) + {% endif %} +
+
+
+ +
+
+
+
授权主机/组
+ +
+
+

授权主机/组

+ 这里包含了用户所有的主机组和组下的主机. +
+
+ {% for group in asset_groups %} +
+
+
+ + {{ group.name }} +
+ 共: {{ group | group_asset_list_count }}台 +
+
+

{{ group.comment }}

+

+ {% for asset in group|group_asset_list %} + {{ asset.ip }}
+ {% endfor %} +

+

+
+
+
+ {% endfor %} + {% if not user|get_user_asset_group %} + (暂无) + {% endif %} +
+
+
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/perm_edit.html b/templates/jperm/perm_edit.html new file mode 100644 index 000000000000..1b2377bacde0 --- /dev/null +++ b/templates/jperm/perm_edit.html @@ -0,0 +1,130 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
主机授权修改
+ +
+ +
+
+ {% if error %} +
{{ error }}
+ {% endif %} + {% if msg %} +
{{ msg }}
+ {% endif %} +
+
+ +
+ + +
+
+ +
+ +
+ +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+
+
+ +
+
+
+ + +
+
+
+
+ +
+
+
+
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/perm_edit_bak.html b/templates/jperm/perm_edit_bak.html new file mode 100644 index 000000000000..cba2d4155d19 --- /dev/null +++ b/templates/jperm/perm_edit_bak.html @@ -0,0 +1,138 @@ +{% extends 'base.html' %} +{% load mytags %} + +{% block content %} + + + {% include 'nav_cat_bar.html' %} +
+
+
+
+ +
+
授权编辑表单 Edit perm of Group
+ +
+ +
+
+
+
+ + +
+
+
+
+ +
+
+
+
+ + +
+
+ +
+
+ +
+

未授权主机组

+
+ + +
+
+ +
+
+ + +
+
+ +

授权主机

+
+ +
+
+
+
+
+
+ + +
+
+
+
+ +
+
+
+
+
+ +{# #} + +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/perm_list.html b/templates/jperm/perm_list.html new file mode 100644 index 000000000000..23b6818df2ee --- /dev/null +++ b/templates/jperm/perm_list.html @@ -0,0 +1,108 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
查看小组
+ +
+ +
+
+ 添加小组 + +
+ + + + + + + + + + + + + + + {% for group in contacts.object_list %} + + + + + + + + + + {% endfor %} + +
组名所属部门成员数目授权主机组数目授权主机数目备注操作
{{ group.name }} {{ group.dept.name }} {{ group.id | member_count }} {{ group.id | ugrp_perm_agrp_count }} {{ group.id | ugrp_perm_asset_count }} {{ group.comment }} + 详情 + 授权编辑 +
+
+
+
+ Showing {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries +
+
+ {% include 'paginator.html' %} +
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/perm_list_ajax.html b/templates/jperm/perm_list_ajax.html new file mode 100644 index 000000000000..64a15a0f2296 --- /dev/null +++ b/templates/jperm/perm_list_ajax.html @@ -0,0 +1,132 @@ +{% load mytags %} +{% ifequal tab 'tab1' %} + + + + + + + + + + + + {% for group in contacts.object_list %} + + + + + + + + {% endfor %} + +
组名 + 类型 + 成员数量授权数量操作
{{ group.name }} {{ group.type|group_type_to_str }} {{ group.id|member_count }} {{ group.id|perm_count }} + 详情 + 编辑 + 删除 +
+
+
+
+ Showing {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries +
+
+
+
+
    + {% if contacts.has_previous %} + + {% else %} + + {% endif %} + {% for page in p.page_range %} + {% ifequal offset1 page %} +
  • {{ page }}
  • + {% else %} +
  • {{ page }}
  • + {% endifequal %} + {% endfor %} + {% if contacts.has_next %} + + {% else %} + + {% endif %} +
+
+
+
+{% else %} + + + + + + + + + + + + {% for user in contacts2.object_list %} + + + + + + + + {% endfor %} + +
用户角色属组主机数量操作
{{ user.name }} {{ user.id | get_role }} {{ user.username | groups_str }} {{ user.id | perm_asset_count }} + 详情 +
+
+
+
+ Showing {{ contacts2.start_index }} to {{ contacts2.end_index }} of {{ p2.count }} entries +
+
+
+
+
    + {% if contacts2.has_previous %} + + {% else %} + + {% endif %} + {% for page in p2.page_range %} + {% ifequal offset1 page %} +
  • {{ page }}
  • + {% else %} +
  • {{ page }}
  • + {% endifequal %} + {% endfor %} + {% if contacts2.has_next %} + + {% else %} + + {% endif %} +
+
+
+
+{% endifequal %} \ No newline at end of file diff --git a/templates/jperm/perm_log.html b/templates/jperm/perm_log.html new file mode 100644 index 000000000000..3b71002e626f --- /dev/null +++ b/templates/jperm/perm_log.html @@ -0,0 +1,93 @@ +{% extends 'base.html' %} +{% block content %} +{% include 'nav_cat_bar.html' %} +
+
+
+
+
+
用户权限申请详细信息列表
+ +
+ +
+
+ +
+
+
+ + + + + + + + + + + + + + + {% for post in contacts.object_list %} + + + + + + + + + + + + + {% endfor %} + +
申请人 所属部门 申请主机组 申请主机 申请时间 批准时间 备注
{{ post.applyer }} {{ post.dept }} {{ post.bisgroup }} {{ post.asset }} {{ post.date_add|date:"Y-m-d H:i:s"}} {{ post.date_end|date:"Y-m-d H:i:s" }} {{ post.comment }}
+
+
+
+ {% include 'paginator.html' %} +
+
+
+
+
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/perm_log_offline.html b/templates/jperm/perm_log_offline.html new file mode 100644 index 000000000000..8b12502773c3 --- /dev/null +++ b/templates/jperm/perm_log_offline.html @@ -0,0 +1,127 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} +
+
+
+
+
+
用户权限申请详细信息列表
+ +
+ +
+
+ +
+
+
+ + + + + + + + + + + + + + + + {% for post in contacts.object_list %} + + + + + + + + + + + {% endfor %} + +
申请人 所属部门 申请主机组 申请主机 批准人 申请时间 备注 详情
{{ post.applyer }} {{ post.dept }} {{ post.bisgroup|ast_to_list }} {{ post.asset|ast_to_list }} {{ post.approver }} {{ post.date_add|date:"Y-m-d H:i:s"}} {{ post.comment }} + 详情 +
+
+
+
+ {% include 'paginator.html' %} +
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/perm_log_online.html b/templates/jperm/perm_log_online.html new file mode 100644 index 000000000000..cda6b07c3c01 --- /dev/null +++ b/templates/jperm/perm_log_online.html @@ -0,0 +1,128 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} +
+
+
+
+
+
用户权限申请详细信息列表
+ +
+ +
+
+ +
+
+
+ + + + + + + + + + + + + + + {% for post in contacts.object_list %} + + + + + + + + + + {% endfor %} + +
申请人 所属部门 申请主机组 申请主机 申请时间 备注 操作
{{ post.applyer }} {{ post.dept }} {{ post.bisgroup|ast_to_list }} {{ post.asset|ast_to_list }} {{ post.date_add|date:"Y-m-d H:i:s"}} {{ post.comment }} + 详情 + {% ifnotequal session_role_id 0 %} + 确认 + 删除 + {% endifnotequal %} +
+
+
+
+ {% include 'paginator.html' %} +
+
+
+
+
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/perm_user_detail.html b/templates/jperm/perm_user_detail.html new file mode 100644 index 000000000000..3a17821a4491 --- /dev/null +++ b/templates/jperm/perm_user_detail.html @@ -0,0 +1,240 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
用户授权详情
+ +
+ +
+
+
+
+ +
+
+ +
+ +
+
+ + + + + + + + + + + + {% for perm in contacts.object_list %} + + + + + + + + {% endfor %} + +
名称用户组主机组备注操作
{{ perm.name }} + {% for user_group in perm.user_group.all %} + {{ user_group.name }} + {% endfor %} + + {% for asset_group in perm.asset_group.all %} + {{ asset_group.name }} + {% endfor %} + {{ perm.comment }} + 详情 + 编辑 + 删除 +
+
+
+
+ Showing {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries +
+
+
+
+
    + {% if contacts.has_previous %} + + {% else %} + + {% endif %} + {% for page in page_range %} + {% ifequal current_page page %} +
  • {{ page }}
  • + {% else %} +
  • {{ page }}
  • + {% endifequal %} + {% endfor %} + {% if contacts.has_next %} + + {% else %} + + {% endif %} +
+
+
+
+
+ +
+{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# {% for user in contacts2.object_list %}#} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# {% endfor %}#} +{# #} +{#
用户角色属组主机数量操作
{{ user.name }} {{ user.id | get_role }} {{ user.username | groups_str }} {{ user.id | perm_asset_count }} #} +{# 详情#} +{#
#} +{#
#} +{#
#} +{#
#} +{# Showing {{ contacts2.start_index }} to {{ contacts2.end_index }} of {{ p2.count }} entries#} +{#
#} +{#
#} +{#
#} +{#
#} +{#
    #} +{# {% if contacts2.has_previous %}#} +{# #} +{# {% else %}#} +{# #} +{# {% endif %}#} +{# {% for page in page_range2 %}#} +{# {% ifequal current_page page %}#} +{#
  • {{ page }}
  • #} +{# {% else %}#} +{#
  • {{ page }}
  • #} +{# {% endifequal %}#} +{# {% endfor %}#} +{# {% if contacts2.has_next %}#} +{# #} +{# {% else %}#} +{# #} +{# {% endif %}#} +{#
#} +{#
#} +{#
#} +{#
#} + +
+
+ +
+ +
+ + + +
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/sudo_add.html b/templates/jperm/sudo_add.html new file mode 100644 index 000000000000..0087da321e00 --- /dev/null +++ b/templates/jperm/sudo_add.html @@ -0,0 +1,226 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
Sudo授权添加
+ +
+ +
+ + +
+ +
+
+
+ {% if error %} +
{{ error }}
+ {% endif %} + {% if msg %} +
{{ msg }}
+ {% endif %} +
+
+ +
+ + 取个名字方便辨识,只支持英文 +
+
+
+ +
+ +
+ + + 允许以哪个用户允许sudo,逗号分隔,默认root + +
+
+
+ +
+ +
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+ +
+
+
+ +
+ +
+ +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+
+ +
+ +
+ +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+
+ + +
+
+ +
+ +
+
+
+
+ +
+
+
+ + +
+
+
+
+
+
+
+ +
+
+
+
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/sudo_cmd_add.html b/templates/jperm/sudo_cmd_add.html new file mode 100644 index 000000000000..9f9e8990ee04 --- /dev/null +++ b/templates/jperm/sudo_cmd_add.html @@ -0,0 +1,148 @@ +{% extends 'base.html' %} + +{% block content %} + {% include 'nav_cat_bar.html' %} +
+
+
+
+
+
填写基本信息
+ +
+
+
+ + +
+ +
+
+
+ {% if error %} +
{{ error }}
+ {% endif %} + {% if msg %} +
{{ msg }}
+ {% endif %} +
+ +
+ + +
+
+ {% ifequal session_role_id 2 %} +
+
+ +
+ +
+
+ {% endifequal %} +
+
+ +
+ + + 输入命令一行一个 + +
+
+
+
+ +
+ +
+
+ +
+
+
+ + +
+
+ +
+
+
+
+
+
+
+
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/sudo_cmd_detail.html b/templates/jperm/sudo_cmd_detail.html new file mode 100644 index 000000000000..26a7b8e72148 --- /dev/null +++ b/templates/jperm/sudo_cmd_detail.html @@ -0,0 +1,48 @@ +{% load mytags %} + + + {% include 'link_css.html' %} + + + + + +
+
+ {% if cmd_group_name %} +

{{ cmd_group.name }} 命令详情

+ {% endif %} +
+ + + {% if cmd_group_name %} + + + + + + + + + + + + + + {% endif %} + + + + +
ID名称部门
{{ cmd_group.id }}{{ cmd_group.name }}{{ cmd_group.dept.name }}
命令: + {{ cmds_str }} +
+
+
+ + \ No newline at end of file diff --git a/templates/jperm/sudo_cmd_list.html b/templates/jperm/sudo_cmd_list.html new file mode 100644 index 000000000000..f7c2d965277c --- /dev/null +++ b/templates/jperm/sudo_cmd_list.html @@ -0,0 +1,140 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
查看命令分组
+ +
+ +
+
+ + +
+
+
+ + + + + + + + + + + + + {% for group in contacts.object_list %} + + + + + + + + {% endfor %} + +
组名命令部门备注操作
{{ group.name }} {{ group.cmd | string_length:50 }} {{ group.dept.name }} {{ group.comment }} + 详情 + 编辑 + 删除 +
+
+
+
+
+
+
+
+ Showing {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries +
+
+
+
+
    + {% if contacts.has_previous %} + + {% else %} + + {% endif %} + {% for page in p.page_range %} + {% ifequal offset1 page %} +
  • {{ page }}
  • + {% else %} +
  • {{ page }}
  • + {% endifequal %} + {% endfor %} + {% if contacts.has_next %} + + {% else %} + + {% endif %} +
+
+
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/sudo_detail.html b/templates/jperm/sudo_detail.html new file mode 100644 index 000000000000..c732a4b37286 --- /dev/null +++ b/templates/jperm/sudo_detail.html @@ -0,0 +1,170 @@ +{% extends 'base.html' %} +{% load mytags %} + +{% block content %} + {% include 'nav_cat_bar.html' %} +
+
+
+
+
+
授权主机/组
+ +
+
+

用户

+ 组下用户. +
+
+
+
+
+ + {{ user_group.name }} +
+ 共: {{ group_user_num }} 用户 +
+
+

{{ user_group.comment }}

+

+ {% for user in users %} + {{ user.name }}
+ {% endfor %} +

+

+
+
+
+ {% if not users %} + (暂无) + {% endif %} +
+
+
+ +
+
+
+
授权主机/组
+ +
+
+

授权主机/组

+ 这里包含了sudo授权所有的主机组和组下的主机. +
+
+ {% for group in asset_groups %} +
+
+
+ + {{ group.name }} +
+ 共: {{ group | group_asset_list_count }}台 +
+
+

{{ group.comment }}

+

+ {% for asset in group|group_asset_list %} + {{ asset.ip }}
+ {% endfor %} +

+

+
+
+
+ {% endfor %} + {% if not asset_groups %} + (暂无) + {% endif %} +
+
+
+ +
+
+
+
授权命令/组
+ +
+
+ {% for cmd_group in cmd_groups %} +
+
+
+ + {{ cmd_group.name }} +
+ 共: {{ cmd_group.id|sudo_cmd_count }} 个 +
+
+

{{ group.comment }}

+

+ {% for cmd in cmd_group|cmd_group_split %} + {{ cmd }}
+ {% endfor %} +

+

+
+
+
+ {% endfor %} + {% if not cmd_groups %} + (暂无) + {% endif %} +
+
+
+ +
+
+ +{% endblock %} \ No newline at end of file diff --git a/templates/jperm/sudo_edit.html b/templates/jperm/sudo_edit.html new file mode 100644 index 000000000000..69b957739bd9 --- /dev/null +++ b/templates/jperm/sudo_edit.html @@ -0,0 +1,155 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
Sudo授权编辑
+ +
+ +
+
+ + +
+
+ {% if error %} +
{{ error }}
+ {% endif %} + {% if msg %} +
{{ msg }}
+ {% endif %} +
+
+ +
+ + + + 允许以哪个用户允许sudo,逗号分隔,默认root + +
+
+ +
+ +
+ +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+
+ +
+ +
+ +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+
+ + +
+
+ +
+ +
+
+
+
+ +
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+{% endblock %} + diff --git a/templates/jperm/sudo_list.html b/templates/jperm/sudo_list.html new file mode 100644 index 000000000000..ab9116e7a87e --- /dev/null +++ b/templates/jperm/sudo_list.html @@ -0,0 +1,129 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
Sudo授权列表
+ +
+ +
+ +
+
+ +
+ +
+
+
+ + + + + + + + + + + + + + + {% for group in contacts.object_list %} + + + + + + + + + + + {% endfor %} + +
组名所属部门成员数目授权主机组数目授权主机数目sudo命令备注操作
{{ group.name }} {{ group.dept.name }} {{ group.id | member_count }} {{ group.id | ugrp_sudo_agrp_count }} {{ group.id | ugrp_sudo_asset_count }} {{ group.id | sudo_cmd_count }} {{ group.comment }} + 详情 + sudo授权 +
+
+
+
+ Showing {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries +
+
+ {% include 'paginator.html' %} +
+
+
+
+
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/juser/chg_info.html b/templates/juser/chg_info.html new file mode 100644 index 000000000000..1658d6a4bd6a --- /dev/null +++ b/templates/juser/chg_info.html @@ -0,0 +1,132 @@ +{% extends 'base.html' %} +{% load mytags %} + + +{% block content %} + {% include 'nav_cat_bar.html' %} +
+
+
+
+
+
编辑用户信息
+ +
+
+
+ {% if error %} +
{{ error }}
+ {% endif %} + {% if msg %} +
{{ msg }}
+ {% endif %} +
+
+ +
+
+
+ +
+ +
+
+
+
+ +
+ + + 登陆web的密码 + +
+
+
+
+ +
+ + + 登陆 Jumpserver 使用的SSH密钥的密码,更改密钥密码需要重新下载密钥 + +
+
+
+ +
+ +
+ +
+
+ +
+
+
+ + +
+
+
+
+
+
+
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/juser/dept_add.html b/templates/juser/dept_add.html new file mode 100644 index 000000000000..799336f81342 --- /dev/null +++ b/templates/juser/dept_add.html @@ -0,0 +1,133 @@ +{% extends 'base.html' %} + +{% block content %} + {% include 'nav_cat_bar.html' %} +
+
+
+
+
+
填写基本信息
+ +
+
+
+ {% if error %} +
{{ error }}
+ {% endif %} + {% if msg %} +
{{ msg }}
+ {% endif %} +
+ +
+ {% if error %} + + {% else %} + + {% endif %} +
+ +
+ +{#
#} +{#
#} +{# #} +{#
#} +{# #} +{#
#} +{#
#} +{#
#} +{# #} +{# #} +{#
#} +{#
#} +{#
#} +{#
#} +{# #} +{#
#} +{#
#} +{#
#} +
+
+ +
+ {% if error %} + + {% else %} + + {% endif %} +
+
+ +
+
+
+ + +
+
+
+
+
+
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/templates/juser/dept_detail.html b/templates/juser/dept_detail.html new file mode 100644 index 000000000000..81aab3f79567 --- /dev/null +++ b/templates/juser/dept_detail.html @@ -0,0 +1,116 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
查看部门
+ +
+ +
+
+ 添加部门 + 删除所选 + +
+ + + + + + + + + + + + + + + {% for dept in contacts.object_list %} + + + + + + + + + + {% endfor %} + +
+ + 部门名称小组数目成员数目主机数目备注操作
+ + {{ dept.name }} {{ dept.id | dept_group_num }} {{ dept.id | dept_user_num}} {{ dept.id | dept_asset_num}} {{ dept.comment }} + 详情 + 编辑 + 删除 +
+
+
+
+ Showing {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries +
+
+ {% include 'paginator.html' %} +
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/juser/dept_edit.html b/templates/juser/dept_edit.html new file mode 100644 index 000000000000..5ade4bad8f5b --- /dev/null +++ b/templates/juser/dept_edit.html @@ -0,0 +1,133 @@ +{% extends 'base.html' %} + +{% block content %} + {% include 'nav_cat_bar.html' %} +
+
+
+
+
+
修改信息
+ +
+
+
+ {% if error %} +
{{ error }}
+ {% endif %} + {% if msg %} +
{{ msg }}
+ {% endif %} +
+ +
+ + +
+ +
+ +
+
+ +
+ + + 用户部门是唯一的 + +
+
+
+ + +
+
+
+
+ +
+
+ +
+
+
+ +
+ +
+
+ +
+
+
+ + +
+
+
+
+
+
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/templates/juser/dept_list.html b/templates/juser/dept_list.html new file mode 100644 index 000000000000..82bf9d539c65 --- /dev/null +++ b/templates/juser/dept_list.html @@ -0,0 +1,126 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
查看部门
+ +
+ +
+
+ 添加部门 + 删除所选 + +
+ + + + + + + + + + + + + + + {% for dept in contacts.object_list %} + + + + + + + + + + {% endfor %} + +
+ + 部门名称小组数目成员数目主机数目备注操作
+ + {{ dept.name }} {{ dept.id | dept_group_num }} {{ dept.id | dept_user_num}} {{ dept.id | dept_asset_num}} {{ dept.comment }} +{# 详情#} + {% ifequal session_role_id 2 %} + 编辑 + 删除 + {% else %} + 编辑 + 删除 + {% endifequal %} +
+
+
+
+ Showing {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries +
+
+ {% include 'paginator.html' %} +
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/juser/dept_user_ajax.html b/templates/juser/dept_user_ajax.html new file mode 100644 index 000000000000..3d73f4eaed40 --- /dev/null +++ b/templates/juser/dept_user_ajax.html @@ -0,0 +1,3 @@ +{% for user in users %} + +{% endfor %} \ No newline at end of file diff --git a/templates/juser/group_add.html b/templates/juser/group_add.html new file mode 100644 index 000000000000..c6867e08c3e5 --- /dev/null +++ b/templates/juser/group_add.html @@ -0,0 +1,152 @@ +{% extends 'base.html' %} + +{% block content %} + {% include 'nav_cat_bar.html' %} +
+
+
+
+
+
填写基本信息
+ +
+
+
+ {% if error %} +
{{ error }}
+ {% endif %} + {% if msg %} +
{{ msg }}
+ {% endif %} +
+ +
+ +
+
+ {% ifequal session_role_id 2 %} +
+
+ +
+ +
+
+ {% endifequal %} +
+
+ +
+ +
+
+
+ + +
+
+
+
+ +
+
+
+
+
+ +
+ +
+
+ +
+
+
+ + +
+
+
+
+
+
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/templates/juser/group_add_ajax.html b/templates/juser/group_add_ajax.html new file mode 100644 index 000000000000..e842df80933f --- /dev/null +++ b/templates/juser/group_add_ajax.html @@ -0,0 +1,4 @@ +{% for user in users %} + +{% endfor %} + diff --git a/templates/juser/group_detail.html b/templates/juser/group_detail.html new file mode 100644 index 000000000000..6046a3b82394 --- /dev/null +++ b/templates/juser/group_detail.html @@ -0,0 +1,43 @@ +{% load mytags %} + + + {% include 'link_css.html' %} + + + + + +
+
+

{{ group.name }} 组中成员

+
+ + + + + + + + + + + {% for user in users %} + + + + + + {% endfor %} + + + +
用户名姓名角色
{{ user.username }}{{ user.name }}{{ user.id|get_role }}
+
+
+ + \ No newline at end of file diff --git a/templates/juser/group_edit.html b/templates/juser/group_edit.html new file mode 100644 index 000000000000..bd31d7abb9da --- /dev/null +++ b/templates/juser/group_edit.html @@ -0,0 +1,160 @@ +{% extends 'base.html' %} + +{% block content %} + {% include 'nav_cat_bar.html' %} +
+
+
+
+
+
填写基本信息
+ +
+
+
+ {% if error %} +
{{ error }}
+ {% endif %} + {% if msg %} +
{{ msg }}
+ {% endif %} +
+ +
+ + +
+
+ {% ifequal session_role_id 2 %} +
+
+ +
+ +
+
+ {% endifequal %} +
+
+ +
+ +
+
+
+ + +
+
+
+
+ +
+
+
+
+
+ +
+ +
+
+ +
+
+
+ + +
+
+
+
+
+
+
+
+ + +{% endblock %} \ No newline at end of file diff --git a/templates/juser/group_list.html b/templates/juser/group_list.html new file mode 100644 index 000000000000..0da320d678e9 --- /dev/null +++ b/templates/juser/group_list.html @@ -0,0 +1,112 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
查看小组
+ +
+ +
+
+ 添加小组 + 删除所选 + +
+ + + + + + + + + + + + + + {% for group in contacts.object_list %} + + + + + + + + + {% endfor %} + +
+ + 组名所属部门成员数目备注操作
+ + {{ group.name }} {{ group.dept.name }} {{ group.id | member_count }} {{ group.comment }} + 编辑 + 删除 +
+
+
+
+ Showing {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries +
+
+ {% include 'paginator.html' %} +
+
+
+
+
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/templates/juser/profile.html b/templates/juser/profile.html new file mode 100644 index 000000000000..7be33cce47dc --- /dev/null +++ b/templates/juser/profile.html @@ -0,0 +1,82 @@ +{% load mytags %} + + + {% include 'link_css.html' %} + + + + + +
+
+

{{ user.name }} 用户详情

+
+ + + + + + + + + + + +{# #} +{# #} + + + + + + + + + + + + +{# #} +{# #} + + + + + + + + + + + +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +{# #} +
ID用户名姓名角色部门Email激活添加时间最后登录
{{ user.id }}{{ user.username }}{{ user.name }}{{ user.id | get_role }}{{ user.dept.name }}{{ user.email }}{{ user.is_active|bool2str }}{{ user.date_joined }}{{ user.last_login }}
添加日期: {{ user.date_joined }}最后登录: {{ user.last_login }}
用户组: + {% for group in user.group.all %} + {{ group.name }} + {% endfor %} +
授权主机组:#} +{# {% for group in user|get_user_asset_group %}#} +{# {{ group.name }}#} +{# {% endfor %}#} +{#
授权主机组#} +{# {% for asset_group in asset_group_permed %}#} +{# {{ asset_group.name }}#} +{# {% endfor %}#} +{#
+
+
+ + \ No newline at end of file diff --git a/templates/juser/user_add.html b/templates/juser/user_add.html new file mode 100644 index 000000000000..2a097fae8438 --- /dev/null +++ b/templates/juser/user_add.html @@ -0,0 +1,212 @@ +{% extends 'base.html' %} +{% load mytags %} + + +{% block content %} + {% include 'nav_cat_bar.html' %} +
+
+
+
+
+
填写基本信息
+ +
+
+
+ {% if error %} +
{{ error }}
+ {% endif %} + {% if msg %} +
{{ msg }}
+ {% endif %} +
+ +
+ +
+
+{#
#} +{#
#} +{# #} +{#
#} +{# #} +{# #} +{# 登陆web的密码#} +{# #} +{#
#} +{#
#} +{#
#} +{#
#} +{# #} +{#
#} +{# #} +{# #} +{# 登陆 Jumpserver 使用的SSH密钥的密码#} +{# #} +{#
#} +{#
#} +
+
+ +
+ +
+
+ {% ifequal session_role_id 2 %} +
+
+ +
+ +
+
+ {% endifequal %} +
+
+ +
+ +
+
+ {% ifequal session_role_id 2 %} +
+
+ +
+ +
+
+ {% endifequal %} +
+
+ +
+ +
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/juser/user_detail.html b/templates/juser/user_detail.html new file mode 100644 index 000000000000..883085ed8615 --- /dev/null +++ b/templates/juser/user_detail.html @@ -0,0 +1,212 @@ +{% extends 'base.html' %} +{% load mytags %} + + +{% block content %} + {% include 'nav_cat_bar.html' %} +
+
+
+
+
+ {{ user.name }} +
+ + + + + + + + + + +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ID{{ user.id }}
用户名{{ user.username }}
姓名{{ user.name }}
角色{{ user.id | get_role }}
部门{{ user.dept.name }}
Email{{ user.email }}
激活{{ user.is_active|bool2str }}
添加日期{{ user.date_joined|date:"Y-m-d H:i:s" }}
最后登录{{ user.last_login|date:"Y-m-d H:i:s" }}
所在用户组 + + {% for group in user.group.all %} + + + + {% endfor %} +
{{ group.name }}
+
+
+
+
+
+
+
+
+
+
授权主机/组
+ +
+
+

用户的所有授权主机

+ 这里包含了用户所有的主机组和组下的主机. +
+
+ {% for group in user|get_user_asset_group %} +
+
+
+ + {{ group.name }} +
+ 共: {{ group | group_asset_list_count }}台 +
+
+

{{ group.comment }}

+

+ {% for asset in group|group_asset_list %} + {{ asset.ip }}
+ {% endfor %} +

+

+
+
+
+ {% endfor %} + {% if not user|get_user_asset_group %} + (无) + {% endif %} +
+
+
+ +
+
+
+
登录记录
+
+ 最近登录 +
+
+
+
+
+ {% for log in logs_last %} +
+ + image + +
+ {{ log.start_time|time_delta }} + {{ log.user }} 登录了 {{ log.host }}.
+ {{ log.start_time|date:"Y-m-d H:i:s" }} +
+
+ {% endfor %} + {% if not logs_last %} + (暂无) + {% endif %} +
+ {% if logs_num > 10 %} + + {% endif %} +
+ + + +
+
+ +
+ +
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/juser/user_edit.html b/templates/juser/user_edit.html new file mode 100644 index 000000000000..c8ad656a3ad8 --- /dev/null +++ b/templates/juser/user_edit.html @@ -0,0 +1,219 @@ +{% extends 'base.html' %} +{% load mytags %} + + +{% block content %} + {% include 'nav_cat_bar.html' %} +
+
+
+
+
+
编辑用户信息
+ +
+
+
+ {% if error %} +
{{ error }}
+ {% endif %} + {% if msg %} +
{{ msg }}
+ {% endif %} +
+ +
+ + +
+
+
+
+ +
+ + + 登陆web的密码 + +
+
+
+
+ +
+ + + 登陆 Jumpserver 使用的SSH密钥的密码,更改密钥密码需要重新下载密钥 + +
+
+
+
+ +
+ +
+
+
+ {% ifequal session_role_id 2 %} +
+ +
+ +
+
+
+ {% endifequal %} +
+ +
+ +
+
+ {% ifequal session_role_id 2 %} +
+
+ +
+ +
+
+ {% endifequal %} +
+
+ +
+ +
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/juser/user_list.html b/templates/juser/user_list.html new file mode 100644 index 000000000000..f9ef7c017282 --- /dev/null +++ b/templates/juser/user_list.html @@ -0,0 +1,139 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
查看用户
+ +
+ +
+
+ 添加用户 + 删除所选 + +
+ + + + + + + + + + + + + + + + + {% for user in contacts.object_list %} + + + + + + + + + + + + {% endfor %} + +
+ + 用户名姓名部门小组角色激活下载密钥操作
+ + {{ user.username }} {{ user.name }} {{ user.dept.name }} {{ user.group.all | group_str2 }} {{ user.id | get_role }}{{ user.is_active|bool2str }}下载 + 详情 + {% ifequal session_role_id 2 %} + 编辑 + 删除 + {% else %} + 编辑 + 删除 + {% endifequal %} +
+
+
+
+ Showing {{ contacts.start_index }} to {{ contacts.end_index }} of {{ p.count }} entries +
+
+ {% include 'paginator.html' %} +
+
+
+
+
+
+ + + +{% endblock %} diff --git a/templates/link_css.html b/templates/link_css.html new file mode 100644 index 000000000000..c5abfaabce4c --- /dev/null +++ b/templates/link_css.html @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 000000000000..00b070dddf83 --- /dev/null +++ b/templates/login.html @@ -0,0 +1,47 @@ + + + + + + + 登录 | JumpServer + + + + + + + + +
+
+
+

+
+ {% if error %} +
{{ error }}
+ {% endif %} +

Welcome to JumpServer

+
+
+ +
+
+ +
+ + + Forgot password? Contact Administrator. +
+

Copyright Jumpserver.org Organization © 2014-2015

+
+
+ + + + + + + + + diff --git a/templates/nav.html b/templates/nav.html new file mode 100644 index 000000000000..7a9874fc2dbf --- /dev/null +++ b/templates/nav.html @@ -0,0 +1,151 @@ +{% ifequal session_role_id 2 %} + +{% endifequal %} +{% ifequal session_role_id 1 %} + +{% endifequal %} + +{% ifequal session_role_id 0 %} + +{% endifequal %} \ No newline at end of file diff --git a/templates/nav_bar_header.html b/templates/nav_bar_header.html new file mode 100644 index 000000000000..d676b1bedca6 --- /dev/null +++ b/templates/nav_bar_header.html @@ -0,0 +1,61 @@ +{% load humanize %} +{% load mytags %} + \ No newline at end of file diff --git a/templates/nav_cat_bar.html b/templates/nav_cat_bar.html new file mode 100644 index 000000000000..78c02e9c193f --- /dev/null +++ b/templates/nav_cat_bar.html @@ -0,0 +1,22 @@ +
+
+

{{ header_title }}

+ +
+
+
+
diff --git a/templates/nav_li_profile.html b/templates/nav_li_profile.html new file mode 100644 index 000000000000..47c8dcd70776 --- /dev/null +++ b/templates/nav_li_profile.html @@ -0,0 +1,47 @@ +{% load mytags %} + + + diff --git a/templates/paginator.html b/templates/paginator.html new file mode 100644 index 000000000000..653e890450fd --- /dev/null +++ b/templates/paginator.html @@ -0,0 +1,72 @@ +
+
+
    + {% if keyword %} + {% if contacts.has_previous %} + + {% else %} + + {% endif %} + {% ifequal show_first 1 %} +
  • 1...
  • + {% endifequal %} + {% for page in page_range %} + {% ifequal current_page page %} +
  • {{ page }}
  • + {% else %} +
  • {{ page }}
  • + {% endifequal %} + {% endfor %} + {% ifequal show_end 1 %} +
  • ...{{ p.num_pages }}
  • + {% endifequal %} + {% if contacts.has_next %} + + {% else %} + + {% endif %} + + {% else %} + {% if contacts.has_previous %} + + {% else %} + + {% endif %} + {% ifequal show_first 1 %} +
  • 1...
  • + {% endifequal %} + {% for page in page_range %} + {% ifequal current_page page %} +
  • {{ page }}
  • + {% else %} +
  • {{ page }}
  • + {% endifequal %} + {% endfor %} + {% ifequal show_end 1 %} +
  • ...{{ p.num_pages }}
  • + {% endifequal %} + {% if contacts.has_next %} + + {% else %} + + {% endif %} + {% endif %} +
+
+
diff --git a/templates/skin_config.html b/templates/skin_config.html new file mode 100644 index 000000000000..2c219ccf086e --- /dev/null +++ b/templates/skin_config.html @@ -0,0 +1,209 @@ +
+
+
+ +
+
+
Configuration
+
+ + Collapse menu + + +
+
+ + +
+
+
+
+ + Fixed sidebar + + +
+
+ + +
+
+
+
+ + Top navbar + + +
+
+ + +
+
+
+
+ + Boxed layout + + +
+
+ + +
+
+
+
+ + Fixed footer + + +
+
+ + +
+
+
+ +
Skins
+ + + +
+
+
+ \ No newline at end of file diff --git a/templates/success.html b/templates/success.html new file mode 100644 index 000000000000..d824e613b82e --- /dev/null +++ b/templates/success.html @@ -0,0 +1,39 @@ + + + + + + + + + Jumpserver | Success + + + + + + + + + + + + +
+

成功

+

{{ msg }}

+ +
+ The server success response the request. Congratulations.
+ You can go back to main page:
首页 +
+
+ + + + + + + + + diff --git a/templates/test.html b/templates/test.html new file mode 100644 index 000000000000..3bcdd3174ad3 --- /dev/null +++ b/templates/test.html @@ -0,0 +1,74 @@ + + + + + + +{##} + + + + +

+ 这是段落中的粗体文本。 +

hello

+ +

+ + + + + + + diff --git a/templates/upload.html b/templates/upload.html new file mode 100644 index 000000000000..a235d11b2585 --- /dev/null +++ b/templates/upload.html @@ -0,0 +1,101 @@ +{% extends 'base.html' %} +{% load mytags %} +{% block content %} +{% include 'nav_cat_bar.html' %} + +
+
+
+
+
+
上传文件
+ +
+
+
+
+
+ +
+ +
+
+
+
+
上传文件到后端服务器的/tmp下,请注意查看
+
+
+
+
+
+
+ + + + + +{% endblock %} \ No newline at end of file diff --git a/webroot/AutoSa/.idea/.name b/webroot/AutoSa/.idea/.name deleted file mode 100644 index ce6809acbfb1..000000000000 --- a/webroot/AutoSa/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -AutoSa \ No newline at end of file diff --git a/webroot/AutoSa/.idea/AutoSa.iml b/webroot/AutoSa/.idea/AutoSa.iml deleted file mode 100644 index fed19458a0a6..000000000000 --- a/webroot/AutoSa/.idea/AutoSa.iml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/webroot/AutoSa/.idea/dataSources.ids b/webroot/AutoSa/.idea/dataSources.ids deleted file mode 100644 index 272c3562c4b0..000000000000 --- a/webroot/AutoSa/.idea/dataSources.ids +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/webroot/AutoSa/.idea/dataSources.xml b/webroot/AutoSa/.idea/dataSources.xml deleted file mode 100644 index 74d15ddf4667..000000000000 --- a/webroot/AutoSa/.idea/dataSources.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - sqlite.xerial - com.mysql.jdbc.Driver - jdbc:mysql://172.10.10.9/jumpserver - root - dfd8dfcfdfcedfc2dfcbdfde - - - - - diff --git a/webroot/AutoSa/.idea/encodings.xml b/webroot/AutoSa/.idea/encodings.xml deleted file mode 100644 index 7c62b52a139b..000000000000 --- a/webroot/AutoSa/.idea/encodings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/webroot/AutoSa/.idea/misc.xml b/webroot/AutoSa/.idea/misc.xml deleted file mode 100644 index 0e219b1ba9b1..000000000000 --- a/webroot/AutoSa/.idea/misc.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/webroot/AutoSa/.idea/modules.xml b/webroot/AutoSa/.idea/modules.xml deleted file mode 100644 index d41ea4d44298..000000000000 --- a/webroot/AutoSa/.idea/modules.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/webroot/AutoSa/.idea/scopes/scope_settings.xml b/webroot/AutoSa/.idea/scopes/scope_settings.xml deleted file mode 100644 index 0d5175ca06be..000000000000 --- a/webroot/AutoSa/.idea/scopes/scope_settings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/webroot/AutoSa/.idea/vcs.xml b/webroot/AutoSa/.idea/vcs.xml deleted file mode 100644 index d2d96f225bbb..000000000000 --- a/webroot/AutoSa/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/webroot/AutoSa/.idea/workspace.xml b/webroot/AutoSa/.idea/workspace.xml deleted file mode 100644 index f7814c55fa81..000000000000 --- a/webroot/AutoSa/.idea/workspace.xml +++ /dev/null @@ -1,931 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1402282329426 - 1402282329426 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/webroot/AutoSa/Assets/models.py b/webroot/AutoSa/Assets/models.py deleted file mode 100644 index 52c6f05accc5..000000000000 --- a/webroot/AutoSa/Assets/models.py +++ /dev/null @@ -1,27 +0,0 @@ -from django.db import models -from UserManage.models import User - - -class IDC(models.Model): - name = models.CharField(max_length=20) - - def __unicode__(self): - return self.name - - -class Assets(models.Model): - id = models.AutoField(primary_key=True) - ip = models.CharField(max_length=20) - port = models.IntegerField(max_length=5) - idc = models.ForeignKey(IDC) - comment = models.CharField(max_length=100, blank=True, null=True) - - def __unicode__(self): - return '%s ' % self.ip - - -class AssetsUser(models.Model): - uid = models.ForeignKey(User) - aid = models.ForeignKey(Assets) - - diff --git a/webroot/AutoSa/Assets/views.py b/webroot/AutoSa/Assets/views.py deleted file mode 100644 index 91ea44a218fb..000000000000 --- a/webroot/AutoSa/Assets/views.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.shortcuts import render - -# Create your views here. diff --git a/webroot/AutoSa/AutoSa/context_processors.py b/webroot/AutoSa/AutoSa/context_processors.py deleted file mode 100644 index 8d3be3c1e144..000000000000 --- a/webroot/AutoSa/AutoSa/context_processors.py +++ /dev/null @@ -1,7 +0,0 @@ -#coding:utf-8 - - -def name_proc(request): - name = request.session.get('username') - admin = request.session.get('admin') - return {'name': name, 'admin': admin} \ No newline at end of file diff --git a/webroot/AutoSa/AutoSa/templatetags/mytags.py b/webroot/AutoSa/AutoSa/templatetags/mytags.py deleted file mode 100644 index b267711b029e..000000000000 --- a/webroot/AutoSa/AutoSa/templatetags/mytags.py +++ /dev/null @@ -1,12 +0,0 @@ -import time -from django import template - -register = template.Library() - - -@register.filter(name='stamp2str') -def stamp2str(value): - try: - return time.strftime('%Y/%m/%d %H:%M:%S', time.localtime(value)) - except AttributeError: - return '0000/00/00 00:00:00' diff --git a/webroot/AutoSa/AutoSa/urls.py b/webroot/AutoSa/AutoSa/urls.py deleted file mode 100644 index f6ca92c9565e..000000000000 --- a/webroot/AutoSa/AutoSa/urls.py +++ /dev/null @@ -1,40 +0,0 @@ -from django.conf.urls import patterns, include, url - -from django.contrib import admin -from AutoSa import views -admin.autodiscover() - -urlpatterns = patterns('', - # Examples: - # url(r'^$', 'AutoSa.views.home', name='home'), - # url(r'^blog/', include('blog.urls')), - - url(r'^admin/', include(admin.site.urls)), - (r'^install/', views.install), - (r'^$', views.index), - (r'^login/$', views.login), - (r'^logout/$', views.logout), - (r'^showUser/$', views.showUser), - (r'^addUser/$', views.addUser), - (r'^chgUser/$', views.chgUser), - (r'^showGroup/$', views.showGroup), - (r'^addGroup/$', views.addGroup), - (r'^chgGroup/$', views.chgGroup), - (r'^showIDC/$', views.showIDC), - (r'^addIDC/$', views.addIDC), - (r'^chgIDC/$', views.chgIDC), - (r'^showSudo/$', views.showSudo), - (r'^chgSudo/$', views.chgSudo), - (r'^showAssets/$', views.showAssets), - (r'^addAssets/$', views.addAssets), - (r'^showPerm/$', views.showPerm), - (r'^addPerm/$', views.addPerm), - (r'^downKey/$', views.downKey), - (r'^chgPass/$', views.chgPass), - (r'^chgKey/$', views.chgKey), - (r'^upFile/$', views.upFile), - (r'^downFile/$', views.downFile), - (r'^logView/$', views.logView), - (r'^logHistory/$', views.logHistory), - (r'^killSession/$', views.killSession), -) diff --git a/webroot/AutoSa/AutoSa/views.py b/webroot/AutoSa/AutoSa/views.py deleted file mode 100644 index ea87a8bc8462..000000000000 --- a/webroot/AutoSa/AutoSa/views.py +++ /dev/null @@ -1,1134 +0,0 @@ -#coding: utf-8 - -from django.http import HttpResponse -from django.template import RequestContext -from django.shortcuts import render_to_response -from django.http import HttpResponseRedirect -from UserManage.models import User, Group, Logs, Pid -from Assets.models import Assets, AssetsUser, IDC -import subprocess -from Crypto.Cipher import AES -from binascii import b2a_hex, a2b_hex -import random -import ConfigParser -import os -import ldap -import ldap.modlist as modlist -import crypt -import hashlib -from UserManage.forms import UserAddForm, GroupAddForm -import paramiko -from django.core.servers.basehttp import FileWrapper -from AutoSa.settings import CONF_DIR -from django.core.paginator import Paginator, InvalidPage, EmptyPage -import time -import datetime - - -cf = ConfigParser.ConfigParser() -cf.read('%s/jumpserver.conf' % CONF_DIR) - -key = cf.get('jumpserver', 'key') -rsa_dir = os.path.join(CONF_DIR, 'keys') -ldap_host = cf.get('jumpserver', 'ldap_host') -ldap_base_dn = cf.get('jumpserver', 'ldap_base_dn') -admin_cn = cf.get('jumpserver', 'admin_cn') -admin_pass = cf.get('jumpserver', 'admin_pass') -log_dir = os.path.join(CONF_DIR, 'logs') -web_socket_host = cf.get('jumpserver', 'web_socket_host') - - -def keygen(num): - """生成随机密码""" - seed = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - salt_list = [] - for i in range(num): - salt_list.append(random.choice(seed)) - salt = ''.join(salt_list) - return salt - - -def bash(cmd): - """执行bash命令""" - return subprocess.call(cmd, shell=True) - - -def md5_crypt(string): - return hashlib.new("md5", string).hexdigest() - - -class PyCrypt(object): - """对称加密解密""" - def __init__(self, key): - self.key = key - self.mode = AES.MODE_CBC - - def encrypt(self, text): - cryptor = AES.new(self.key, self.mode, b'0000000000000000') - length = 16 - count = len(text) - if count < length: - add = (length - count) - text += ('\0' * add) - elif count > length: - add = (length - (count % length)) - text += ('\0' * add) - ciphertext = cryptor.encrypt(text) - return b2a_hex(ciphertext) - - def decrypt(self, text): - cryptor = AES.new(self.key, self.mode, b'0000000000000000') - plain_text = cryptor.decrypt(a2b_hex(text)) - return plain_text.rstrip('\0') - - -def rsa_gen(username, key_pass, rsa_dir=rsa_dir): - rsa_file = '%s/%s' % (rsa_dir, username) - pub_file = '%s.pub' % rsa_file - authorized_file = '/home/%s/.ssh/authorized_keys' % username - if os.path.exists(rsa_file): - os.unlink(rsa_file) - ret = bash('ssh-keygen -t rsa -f %s -P %s &> /dev/null && echo "######## rsa_gen Ok."' % (rsa_file, key_pass)) - if not ret: - try: - if not os.path.isdir('/home/%s/.ssh' % username): - os.mkdir('/home/%s/.ssh' % username) - pub = open(pub_file, 'r') - authorized = open(authorized_file, 'w') - authorized.write(pub.read()) - pub.close() - authorized.close() - except Exception: - return 1 - else: - return 0 - - -class LDAPMgmt(): - def __init__(self, - ldap_host=ldap_host, - ldap_base_dn=ldap_base_dn, - admin_cn=admin_cn, - admin_pass=admin_pass): - self.ldap_host = ldap_host - self.ldap_base_dn = ldap_base_dn - self.admin_cn = admin_cn - self.admin_pass = admin_pass - self.conn = ldap.initialize(ldap_host) - self.conn.set_option(ldap.OPT_REFERRALS, 0) - self.conn.protocol_version = ldap.VERSION3 - self.conn.simple_bind_s(admin_cn, admin_pass) - - def list(self, filter, scope=ldap.SCOPE_SUBTREE, attr=None): - result = {} - try: - ldap_result = self.conn.search_s(self.ldap_base_dn, scope, filter, attr) - for entry in ldap_result: - name, data = entry - for k, v in data.items(): - print '%s: %s' % (k, v) - result[k] = v - return result - except ldap.LDAPError, e: - print e - - def add(self, dn, attrs): - try: - ldif = modlist.addModlist(attrs) - self.conn.add_s(dn, ldif) - except ldap.LDAPError, e: - print e - - def modify(self, dn, attrs): - try: - attr_s = [] - for k, v in attrs.items(): - attr_s.append((2, k, v)) - self.conn.modify_s(dn, attr_s) - except ldap.LDAPError, e: - print e - - def delete(self, dn): - try: - self.conn.delete_s(dn) - except ldap.LDAPError, e: - print e - - -def gen_sha512(salt, password): - return crypt.crypt(password, '$6$%s$' % salt) - - -def group_member(username): - member = [] - user = User.objects.get(username=username) - for group in user.group.all(): - member.extend(group.user_set.all()) - return list(set(member)) - - -def user_assets(username): - assets = [] - user = User.objects.get(username=username) - for asset in user.assetsuser_set.all(): - assets.append(asset.aid) - return assets - - -def login_required(func): - """要求登录的装饰器""" - def _deco(request, *args, **kwargs): - if not request.session.get('username'): - return HttpResponseRedirect('/login/') - return func(request, *args, **kwargs) - return _deco - - -def admin_required(func): - """要求用户是admin的装饰器""" - def _deco(request, *args, **kwargs): - if request.session.get('admin') < 1: - return HttpResponseRedirect('/') - return func(request, *args, **kwargs) - return _deco - - -def superuser_required(func): - """要求用户是superuser""" - def _deco(request, *args, **kwargs): - if request.session.get('admin') != 2: - return HttpResponseRedirect('/') - return func(request, *args, **kwargs) - return _deco - - -def is_admin_role(request): - if request.session.get('admin') > 0: - return True - else: - return False - - -def is_admin_user(request): - if request.session.get('admin') == 1: - return True - else: - return False - - -def is_super_user(request): - if request.session.get('admin') == 2: - return True - else: - return False - - -def install(request): - user = User.objects.filter(username='admin') - if user: - error = '已经安装,请出重复安装.' - return render_to_response('info.html', {'error': error}) - else: - u = User( - id=800, - username='admin', - password=md5_crypt('admin'), - key_pass=md5_crypt('admin'), - name='admin', - is_admin=False, - is_superuser=True, - ldap_password=md5_crypt('admin')) - u.save() - msg = '安装成功' - return render_to_response('info.html', {'msg': msg}) - - -def login(request): - """登录界面""" - if request.session.get('username'): - return HttpResponseRedirect('/') - if request.method == 'GET': - return render_to_response('login.html') - else: - username = request.POST.get('username') - password = request.POST.get('password') - user = User.objects.filter(username=username) - if user: - user = user[0] - if md5_crypt(password) == user.password: - request.session['username'] = username - if user.is_admin: - request.session['admin'] = 1 - elif user.is_superuser: - request.session['admin'] = 2 - else: - request.session['admin'] = 0 - return HttpResponseRedirect('/') - else: - error = '密码错误,请重新输入。' - else: - error = '用户不存在。' - return render_to_response('login.html', {'error': error}) - - -def logout(request): - """注销登录调用""" - if request.session.get('username'): - del request.session['username'] - del request.session['admin'] - return HttpResponseRedirect('/login/') - - -@login_required -def downKey(request): - """下载key""" - username = request.session.get('username') - if request.session.get('admin') == 1: - user = User.objects.get(username=username) - if user in group_member(username): - username = request.GET.get('username') - elif request.session.get('admin') == 2: - username = request.GET.get('username') - - filename = '%s/%s' % (rsa_dir, username) - try: - f = open(filename) - except IOError: - error = u'密钥文件不存在' - return render_to_response('info.html', {'error': error}) - data = f.read() - f.close() - response = HttpResponse(data, content_type='application/octet-stream') - response['Content-Disposition'] = 'attachment; filename=%s.rsa' % username - return response - - -@login_required -def index(request): - """主页""" - username = request.session.get('username') - name = User.objects.filter(username=username) - assets = [] - if name: - user_assets = AssetsUser.objects.filter(uid=name[0]) - if user_assets: - for user_asset in user_assets: - assets.append(user_asset.aid) - return render_to_response('index.html', {'index': 'active', 'assets': assets}, - context_instance=RequestContext(request)) - - -@admin_required -def showUser(request): - """查看所有用户""" - info = '' - error = '' - - if is_super_user(request): - users_all = User.objects.all() - else: - users_all = group_member(request.session.get('username')) - - paginator = Paginator(users_all, 20) - - try: - page = int(request.GET.get('page', 1)) - except ValueError: - page = 1 - - try: - users = paginator.page(page) - except (EmptyPage, InvalidPage): - users = paginator.page(paginator.num_pages) - - if request.method == 'POST': - selected_user = request.REQUEST.getlist('selected') - if selected_user: - for user_id in selected_user: - # 从数据库中删除 - try: - user = User.objects.get(id=user_id) - if user.is_admin or user.is_superuser: - if is_admin_user(request): - return HttpResponseRedirect('/showUser/') - username = user.username - user.delete() - except Exception, e: - error = u'数据库中用户删除错误' + unicode(e) - - # 在bash中删除 - bash_del = bash("userdel -r %s" % username) - if bash_del != 0: - error = u'bash中用户删除错误' - - # 从LDAP中删除 - try: - ldap_del = LDAPMgmt() - user_dn = "uid=%s,ou=People,%s" % (username, ldap_base_dn) - group_dn = "cn=%s,ou=Group,%s" % (username, ldap_base_dn) - sudo_dn = 'cn=%s,ou=Sudoers,%s' % (username, ldap_base_dn) - ldap_del.delete(user_dn) - ldap_del.delete(group_dn) - ldap_del.delete(sudo_dn) - except Exception, e: - error = u'ldap中用户删除错误' + unicode(e) - - if not error: - info = '用户删除成功' - - return render_to_response('showUser.html', - {'users': users, - 'info': info, - 'error': error, - 'user_menu': 'active'}, - context_instance=RequestContext(request)) - - -@admin_required -def addUser(request): - """添加用户""" - msg = '' - form = UserAddForm() - jm = PyCrypt(key) - - if request.method == 'POST': - form = UserAddForm(request.POST) - if form.is_valid(): - user = form.cleaned_data - username = user['username'] - password = user['password'] - key_pass = user['key_pass'] - name = user['name'] - is_admin = user['is_admin'] - is_superuser = user['is_superuser'] - ldap_password = keygen(16) - group_post = user['group'] - groups = [] - - # 如果用户是admin,那么不能委任其他admin或者超级用户 - if is_admin_user(request): - is_admin = False - is_superuser = False - - # 组 - for group_name in group_post: - groups.append(Group.objects.get(name=group_name)) - - # 数据中保存用户,如果失败就返回 - u = User( - username=username, - password=md5_crypt(password), - key_pass=jm.encrypt(key_pass), - name=name, - is_admin=is_admin, - is_superuser=is_superuser, - ldap_password=jm.encrypt(ldap_password)) - try: - u.save() - u.group = groups - u.save() - except Exception, e: - error = u'数据库插入用户错误' + unicode(e) - return render_to_response('addUser.html', {'user_menu': 'active', 'form': form, 'error': error}, - context_instance=RequestContext(request)) - - # 系统中添加用户 - ret_add = bash('useradd %s' % username) - ret_passwd = bash('echo %s | passwd --stdin %s' % (password, username)) - ret_rsa = rsa_gen(username, key_pass) - - if [ret_add, ret_passwd, ret_rsa].count(0) < 3: - error = u'跳板机添加用户失败' - bash('userdel -r %s' % username) - u.delete() - return render_to_response('addUser.html', {'user_menu': 'active', 'form': form, 'error': error}, - context_instance=RequestContext(request)) - - # 添加到ldap中 - user_dn = "uid=%s,ou=People,%s" % (username, ldap_base_dn) - password_sha512 = gen_sha512(keygen(6), ldap_password) - user_attr = { - 'uid': [str(username)], - 'cn': [str(username)], - 'objectClass': ['account', 'posixAccount', 'top', 'shadowAccount'], - 'userPassword': ['{crypt}%s' % password_sha512], - 'shadowLastChange': ['16328'], - 'shadowMin': ['0'], - 'shadowMax': ['99999'], - 'shadowWarning': ['7'], - 'loginShell': ['/bin/bash'], - 'uidNumber': [str(u.id)], - 'gidNumber': [str(u.id)], - 'homeDirectory': [str('/home/%s' % username)]} - - group_dn = "cn=%s,ou=Group,%s" % (username, ldap_base_dn) - group_attr = { - 'objectClass': ['posixGroup', 'top'], - 'cn': [str(username)], - 'userPassword': ['{crypt}x'], - 'gidNumber': [str(u.id)] - } - - sudo_dn = 'cn=%s,ou=Sudoers,%s' % (username, ldap_base_dn) - sudo_attr = { - 'objectClass': ['top'], - 'objectClass': ['sudoRole'], - 'cn': ['%s' % str(username)], - 'sudoCommand': ['/bin/pwd'], - 'sudoHost': ['192.168.1.1'], - 'sudoOption': ['!authenticate'], - 'sudoRunAsUser': ['root'], - 'sudoUser': ['%s' % str(username)] - } - ldap_conn = LDAPMgmt() - try: - ldap_conn.add(user_dn, user_attr) - ldap_conn.add(group_dn, group_attr) - ldap_conn.add(sudo_dn, sudo_attr) - except Exception, e: - error = u'添加ladp用户失败' + unicode(e) - try: - bash('userdel -r %s' % username) - u.delete() - ldap_conn.delete(user_dn) - ldap_conn.delete(group_dn) - ldap_conn.delete(sudo_dn) - except Exception: - pass - return render_to_response('addUser.html', {'user_menu': 'active', 'form': form, 'error': error}, - context_instance=RequestContext(request)) - - msg = u'添加用户成功' - return render_to_response('addUser.html', {'user_menu': 'active', 'form': form, 'msg': msg}, - context_instance=RequestContext(request)) - - -@admin_required -def chgUser(request): - """修改用户信息""" - error = '' - msg = '' - - if request.method == "GET": - username = request.GET.get('username') - if not username: - return HttpResponseRedirect('/showUser/') - user = User.objects.get(username=username) - ori_is_admin = "checked" if user.is_admin else '' - ori_is_superuser = 'checked' if user.is_superuser else '' - all_groups = Group.objects.all() - - return render_to_response('chgUser.html', - {'user': user, 'user_menu': 'active', 'is_admin': ori_is_admin, - 'is_superuser': ori_is_superuser, 'groups': all_groups}, - context_instance=RequestContext(request)) - else: - username = request.POST.get('username') - name = request.POST.get('name') - is_admin = request.POST.get('is_admin') - is_superuser = request.POST.get('is_superuser') - group_post = request.REQUEST.getlist('group') - groups = [] - user = User.objects.get(username=username) - - # 属组的获取 - for group_name in group_post: - groups.append(Group.objects.get(name=group_name)) - - # 如果用户是admin,那么不能委任其他admin或者超级用户 - if is_admin_user(request): - is_admin = False - is_superuser = False - else: - is_admin = True if is_admin else False - is_superuser = True if is_superuser else False - - if '' in [username, name, group_post]: - error = u'带*内容不能为空' - - if error: - return render_to_response('info.html', {'error': error}) - - u = User.objects.get(username=username) - u.name = name - u.is_admin = is_admin - u.is_superuser = is_superuser - u.group = groups - - u.save() - msg = u'修改用户信息成功' - return render_to_response('info.html', {'msg': msg}) - - -@superuser_required -def addGroup(request): - error = '' - msg = '' - if request.method == 'POST': - group_name = request.POST.get('name') - if group_name: - group = Group(name=group_name) - group.save() - msg = u'%s 属组添加成功' % group_name - else: - error = u'不能为空' - return render_to_response('addGroup.html', - {'error': error, 'msg': msg, 'user_menu': 'active'}, - context_instance=RequestContext(request)) - - -@superuser_required -def showGroup(request): - error = '' - msg = '' - groups = Group.objects.all() - if request.method == 'POST': - selected_group = request.REQUEST.getlist('selected') - if selected_group: - for group_id in selected_group: - group = Group.objects.get(id=group_id) - group.delete() - msg = '删除成功' - else: - error = '请选择删除的组' - - return render_to_response('showGroup.html', {'error': error, 'msg': msg, 'groups': groups, 'user_menu': 'active'}, - context_instance=RequestContext(request)) - - -@superuser_required -def chgGroup(request): - error = '' - msg = '' - if request.method == 'GET': - group_id = request.GET.get('id', None) - if group_id: - group = Group.objects.get(id=group_id) - else: - return HttpResponseRedirect('/showGroup/') - else: - group_id = request.POST.get('id') - group_name = request.POST.get('name') - - if not group_name: - error = u'不能为空' - return render_to_response('info.html', {'error': error}) - else: - group = Group.objects.get(id=group_id) - group.name = group_name - group.save() - msg = u'修改成功' - - return render_to_response('chgGroup.html', {'group': group, 'error': error, 'msg': msg, 'user_menu': 'active'}, - context_instance=RequestContext(request)) - - -@superuser_required -def showIDC(request): - error = '' - msg = '' - idcs = IDC.objects.all() - - if request.method == 'POST': - selected_idc = request.REQUEST.getlist('selected') - if selected_idc: - for idc_id in selected_idc: - idc = IDC.objects.get(id=idc_id) - idc.delete() - msg = '删除成功' - - return render_to_response('showIDC.html', - {'idcs': idcs, 'error': error, 'msg': msg, 'asset_menu': 'active'}, - context_instance=RequestContext(request)) - - -@superuser_required -def chgIDC(request): - error = '' - msg = '' - if request.method == 'GET': - idc_id = request.GET.get('id', None) - if not idc_id: - return HttpResponseRedirect('/showIDC/') - else: - idc = IDC.objects.get(id=idc_id) - else: - idc_id = request.POST.get('id') - idc_name = request.POST.get('name') - if not idc_name: - error = u'不能为空' - return render_to_response('info.html', {'error': error}) - else: - idc = Group.objects.get(id=idc_id) - idc.name = idc_name - idc.save() - msg = u'修改成功' - - return render_to_response('chgGroup.html', {'idc': idc, 'error': error, 'msg': msg, 'asset_menu': 'active'}, - context_instance=RequestContext(request)) - - -@superuser_required -def addIDC(request): - error = '' - msg = '' - if request.method == 'POST': - idc_name = request.POST.get('name') - if idc_name: - idc = IDC(name=idc_name) - idc.save() - msg = u'%s IDC添加成功' % idc_name - else: - error = u'不能为空' - return render_to_response('addIDC.html', - {'error': error, 'msg': msg, 'user_menu': 'active'}, - context_instance=RequestContext(request)) - -@admin_required -def showSudo(request): - if request.method == 'GET': - username = request.GET.get('username') - if not username: - return HttpResponseRedirect('/showUser/') - l = LDAPMgmt() - result = l.list('entryDN=cn=%s,ou=Sudoers,%s' % (str(username), ldap_base_dn), attr=['sudoHost', 'sudoCommand']) - sudoHost = result.get('sudoHost') - sudoCommand = result.get('sudoCommand') - return render_to_response('showSudo.html', - {'username': username, - 'sudoHost': sudoHost, - 'sudoCommand': sudoCommand, - 'user_menu': 'active'}, - context_instance=RequestContext(request)) - -@admin_required -def chgSudo(request): - if request.method == 'GET': - username = request.GET.get('username') - if not username: - return HttpResponseRedirect('/showUser/') - return render_to_response('chgSudo.html', - {'username': username, - 'user_menu': 'active', - }, - context_instance=RequestContext(request)) - else: - l = LDAPMgmt() - username = request.POST.get('username') - user_dn = 'cn=%s,ou=Sudoers,%s' % (str(username), ldap_base_dn) - msg = '' - if request.POST.get('add_host') or request.POST.get('del_host'): - host = request.POST.get('add_host') if request.POST.get('add_host') else request.POST.get('del_host') - hosts = str(host).split(',') - ori_hosts = l.list('entryDN=cn=%s,ou=Sudoers,%s' % - (str(username), ldap_base_dn), attr=['sudoHost']).get('sudoHost') - - if request.POST.get('add_host'): - if not ori_hosts: - ori_hosts = [] - ori_hosts.extend(hosts) - new_hosts = list(set(ori_hosts)) - else: - new_hosts = list(set(ori_hosts) - set(hosts)) - l.modify(user_dn, {'sudoHost': new_hosts}) - - msg = '修改sudo主机成功' % hosts - - if request.POST.get('add_cmd') or request.POST.get('del_cmd'): - cmd = request.POST.get('add_cmd') if request.POST.get('add_cmd') else request.POST.get('del_cmd') - cmds = str(cmd).split(',') - ori_cmds = l.list('entryDN=cn=%s,ou=Sudoers,%s' % - (str(username), ldap_base_dn), attr=['sudoCommand']).get('sudoCommand') - if request.POST.get('add_cmd'): - if not ori_cmds: - ori_cmds = [] - ori_cmds.extend(cmds) - new_cmds = list(set(ori_cmds)) - else: - new_cmds = list(set(ori_cmds) - set(cmds)) - - l.modify(user_dn, {'sudoCommand': new_cmds}) - msg = '修改sudo命令成功' - - if msg: - return render_to_response('info.html', - {'msg': msg}) - else: - return HttpResponseRedirect('/chgSudo/?username=%s' % username) - - - -@admin_required -def showAssets(request): - """查看服务器""" - info = '' - if request.session.get('admin') < 2: - assets_all = [] - username = request.session.get('username') - user = User.objects.get(username=username) - for asset in user.assetsuser_set.all(): - assets_all.append(asset.aid) - else: - assets_all = Assets.objects.all().order_by('ip') - paginator = Paginator(assets_all, 20) - - try: - page = int(request.GET.get('page', 1)) - except ValueError: - page = 1 - - try: - assets = paginator.page(page) - except (EmptyPage, InvalidPage): - assets = paginator.page(paginator.num_pages) - - if request.method == 'POST': - if request.session.get('admin') < 2: - return HttpResponseRedirect('/showAssets/') - assets_del = request.REQUEST.getlist('selected') - for asset_id in assets_del: - asset_del = Assets.objects.get(id=asset_id) - asset_del.delete() - info = '主机信息删除成功!' - return render_to_response('showAssets.html', {'assets': assets, 'info': info, 'asset_menu': 'active'}, - context_instance=RequestContext(request)) - - -@superuser_required -def addAssets(request): - """添加服务器""" - error = '' - msg = '' - idcs = IDC.objects.all() - if request.method == 'POST': - ip = request.POST.get('ip') - port = request.POST.get('port') - idc = request.POST.get('idc') - comment = request.POST.get('comment') - - if '' in (ip, port, idc): - error = '带*号内容不能为空。' - elif Assets.objects.filter(ip=ip): - error = '主机已存在。' - if not error: - idc = IDC.objects.get(id=idc) - asset = Assets(ip=ip, port=port, idc=idc, comment=comment) - asset.save() - msg = u'%s 添加成功' % ip - - return render_to_response('addAssets.html', {'msg': msg, 'error': error, 'idcs': idcs, 'asset_menu': 'active'}, - context_instance=RequestContext(request)) - - -@admin_required -def showPerm(request): - """查看权限""" - if is_super_user(request): - users = User.objects.all() - else: - users = group_member(request.session.get('username')) - - if request.method == 'POST': - assets_del = request.REQUEST.getlist('selected') - username = request.POST.get('username') - user = User.objects.get(username=username) - - for asset_id in assets_del: - asset = Assets.objects.get(id=int(asset_id)) - asset_user_del = AssetsUser.objects.get(uid=user, aid=asset) - asset_user_del.delete() - return HttpResponseRedirect('/showPerm/?username=%s' % username) - - elif request.method == 'GET': - if request.GET.get('username'): - username = request.GET.get('username') - user = User.objects.get(username=username) - assets_user = AssetsUser.objects.filter(uid=user.id) - return render_to_response('perms.html', - {'user': user, 'assets': assets_user, 'perm_menu': 'active'}, - context_instance=RequestContext(request)) - return render_to_response('showPerm.html', {'users': users, 'perm_menu': 'active'}, - context_instance=RequestContext(request)) - - -@admin_required -def addPerm(request): - """增加授权""" - if is_super_user(request): - users = User.objects.all() - else: - users = group_member(request.session.get('username')) - - have_assets = [] - if request.method == 'POST': - username = request.POST.get('username') - assets_id = request.REQUEST.getlist('asset') - user = User.objects.get(username=username) - for asset_id in assets_id: - asset = Assets.objects.get(id=asset_id) - asset_user = AssetsUser(uid=user, aid=asset) - asset_user.save() - return HttpResponseRedirect('/addPerm/?username=%s' % username) - - elif request.method == 'GET': - if request.GET.get('username'): - username = request.GET.get('username') - user = User.objects.get(username=username) - assets_user = AssetsUser.objects.filter(uid=user.id) - for asset_user in assets_user: - have_assets.append(asset_user.aid) - - if request.session.get('admin') == 2: - all_assets = Assets.objects.all() - else: - all_assets = user_assets(request.session.get('username')) - other_assets = list(set(all_assets) - set(have_assets)) - return render_to_response('addUserPerm.html', - {'user': user, 'assets': other_assets, 'perm_menu': 'active'}, - context_instance=RequestContext(request)) - - return render_to_response('addPerm.html', - {'users': users, 'perm_menu': 'active'}, - context_instance=RequestContext(request)) - - -@login_required -def chgPass(request): - """修改登录密码""" - error = '' - msg = '' - is_self = False - - if request.method == 'GET': - if is_admin_role(request): - username = request.GET.get('username') - else: - username = request.session.get('username') - is_self = True - - return render_to_response('chgPass.html', - {'username': username, 'is_self': is_self, 'user_menu': 'active'}, - context_instance=RequestContext(request)) - else: - username = request.POST.get('username') - user = User.objects.get(username=username) - password = request.POST.get('password') - password_again = request.POST.get('password_again') - - if not is_admin_role(request): - oldpass = request.POST.get('oldpass') - if md5_crypt(oldpass) != user.password: - error = '原来密码不正确' - - if password != password_again: - error = '密码不匹配' - - if error: - return render_to_response('info.html', {'error': error}) - - user.password = md5_crypt(password) - user.save() - - return render_to_response('info.html', {'msg': '修改密码成功'}) - - -@login_required -def chgKey(request): - """修改密钥密码""" - error = '' - msg = '' - is_self = False - - if request.method == 'GET': - if is_admin_role(request): - username = request.GET.get('username') - else: - username = request.session.get('username') - is_self = True - - return render_to_response('chgKey.html', - {'username': username, 'is_self': is_self, 'user_menu': 'active'}, - context_instance=RequestContext(request)) - else: - username = request.POST.get('username') - user = User.objects.get(username=username) - password = request.POST.get('password') - password_again = request.POST.get('password_again') - jm = PyCrypt(key) - - if not is_admin_role(request): - oldpass = request.POST.get('oldpass') - if jm.encrypt(oldpass) != user.key_pass: - error = '原来密码不正确' - - if password != password_again: - error = '密码不匹配' - - if len(password) < 5: - error = '密码长度需要>5' - - if error: - return render_to_response('info.html', {'error': error}) - - keyfile = '%s/%s' % (rsa_dir, username) - ret = bash('ssh-keygen -p -P %s -N %s -f %s' % (jm.decrypt(user.key_pass), password, keyfile)) - if ret != 0: - error = '更改私钥密码错误' - return render_to_response('info.html', {'error': error}) - user.key_pass = jm.encrypt(password) - user.save() - - return render_to_response('info.html', {'msg': '修改密码成功'}) - - -@login_required -def upFile(request): - username = request.session.get('username') - msg = '' - error = '' - upload_dir = '/tmp/upload/%s' % username - if request.method == 'POST': - host = request.POST.get('host') - path = request.POST.get('path') - upload_file = request.FILES.get('file', None) - - if upload_file: - if not os.path.exists(upload_dir): - os.makedirs(upload_dir) - filename = '%s/%s' % (upload_dir, upload_file.name) - f = open(filename, 'wb') - for chunk in upload_file.chunks(): - f.write(chunk) - f.close() - asset = Assets.objects.get(ip=host) - if asset: - port = asset.port - jm = PyCrypt(key) - user = User.objects.get(username=username) - try: - t = paramiko.Transport((host, port)) - t.connect(username=username, password=jm.decrypt(user.ldap_password)) - sftp = paramiko.SFTPClient.from_transport(t) - sftp.put(filename, '%s/%s' % (path, upload_file.name)) - msg = u'上传成功,位于 %s主机,位置 %s.' % (host, path) - uplog_dir = os.path.join(log_dir, 'upload') - if not os.path.isdir(uplog_dir): - os.mkdir(uplog_dir) - filename = os.path.join(uplog_dir, '%s.log' % time.strftime('%Y%m%d')) - f = open(filename, 'a') - f.write('DateTime: %s User: %s Host: %s File: %s\n' % - (time.strftime('%Y/%m/%d %H:%M:%S'), username, host, path)) - f.close() - except paramiko.AuthenticationException: - error = u'密码不对 或者 你用的admin用户' - - return render_to_response('info.html', {'msg': msg, 'error': error}) - else: - return render_to_response('info.html', {'error': u"上传失败"}) - - return render_to_response('upFile.html', - {'username': username}, - context_instance=RequestContext(request)) - - -@login_required -def downFile(request): - username = request.session.get('username') - if request.method == 'POST': - host = request.POST.get('host') - path = request.POST.get('path') - download_dir = '/tmp/download/%s' % username - download_file = '%s/%s' % (download_dir, os.path.basename(path)) - if not os.path.exists(download_dir): - os.makedirs(download_dir) - asset = Assets.objects.get(ip=host) - jm = PyCrypt(key) - port = asset.port - user = User.objects.get(username=username) - t = paramiko.Transport((host, port)) - t.connect(username=username, password=jm.decrypt(user.ldap_password)) - sftp = paramiko.SFTPClient.from_transport(t) - sftp.get(path, download_file) - if os.path.isfile(download_file): - downlog_dir = os.path.join(log_dir, 'download') - if not os.path.isdir(downlog_dir): - os.mkdir(downlog_dir) - filename = os.path.join(downlog_dir, '%s.log' % time.strftime('%Y%m%d')) - f = open(filename, 'a') - f.write('DateTime: %s User: %s Host: %s File: %s\n' % - (time.strftime('%Y/%m/%d %H:%M:%S'), username, host, path)) - f.close() - wrapper = FileWrapper(open(download_file)) - response = HttpResponse(wrapper, content_type='application/octet-stream') - response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(path) - return response - - return render_to_response('downFile.html', - {'username': username}, - context_instance=RequestContext(request)) - - -@admin_required -def logView(request): - thirtyDayAgo = (datetime.datetime.now() - datetime.timedelta(30)) - thirtyDayAgoStamp = int(time.mktime(thirtyDayAgo.timetuple())) - logs_all = Logs.objects.filter(start_time__gt=thirtyDayAgoStamp).order_by("-id") - paginator = Paginator(logs_all, 20) - - try: - page = int(request.GET.get('page', 1)) - except ValueError: - page = 1 - - try: - logs = paginator.page(page) - except (EmptyPage, InvalidPage): - logs = paginator.page(paginator.num_pages) - - return render_to_response('logView.html', - {'logs': logs, 'web_socket_host': web_socket_host}, - context_instance=RequestContext(request)) - - -@admin_required -def logHistory(request): - if request.method == 'GET': - logid = request.GET.get('id', 0) - log = Logs.objects.filter(id=int(logid)) - if log: - log = log[0] - log_his = "%s.his" % log.logfile - if os.path.isfile(log_his): - f = open(log_his) - content = f.read() - return HttpResponse(content) - - -@admin_required -def killSession(request): - if request.method == 'GET': - logid = request.GET.get('id', 0) - pid = Pid.objects.filter(logid=logid) - if pid: - pid = pid[0] - os.kill(pid.cpid, 9) - return render_to_response('info.html', {'msg': u'结束会话成功,返回中.'}) - - - - - - - - - - - - - - - - - - - diff --git a/webroot/AutoSa/UserManage/forms.py b/webroot/AutoSa/UserManage/forms.py deleted file mode 100644 index 9c376d0ee6a7..000000000000 --- a/webroot/AutoSa/UserManage/forms.py +++ /dev/null @@ -1,48 +0,0 @@ -# coding: utf-8 - -from django import forms -from UserManage.models import Group - - -class GroupAddForm(forms.Form): - name = forms.CharField(max_length=30) - - -class UserAddForm(forms.Form): - username = forms.CharField(max_length=30, - widget=forms.TextInput( - attrs={'class': 'form-control', 'placeholder': '用户名'})) - password = forms.CharField(max_length=30, - widget=forms.PasswordInput( - attrs={'class': 'form-control', 'placeholder': '密码'})) - password_again = forms.CharField(max_length=30, - widget=forms.PasswordInput( - attrs={'class': 'form-control', 'placeholder': '确认密码'})) - key_pass = forms.CharField(max_length=30, min_length=6, - widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '密钥密码'})) - key_pass_again = forms.CharField(max_length=30, - widget=forms.PasswordInput( - attrs={'class': 'form-control', 'placeholder': '确认密码'})) - name = forms.CharField(max_length=30, - widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': '姓名'})) - group = forms.ModelMultipleChoiceField(queryset=Group.objects.all(), - widget=forms.SelectMultiple(attrs={'class': 'form-control'})) - is_admin = forms.BooleanField(required=False) - is_superuser = forms.BooleanField(required=False) - - def clean_password_again(self): - password = self.cleaned_data['password'] - password_again = self.cleaned_data['password_again'] - - if password != password_again: - raise forms.ValidationError(u'密码二次输入不一致. ') - return password_again - - def clean_key_pass_again(self): - key_pass = self.data['key_pass'] - key_pass_again = self.data['key_pass_again'] - if key_pass != key_pass_again: - raise forms.ValidationError(u'密码二次输入不一致. ') - if len(key_pass) < 6: - raise forms.ValidationError(u'密码二次输入不一致. ') - return key_pass_again \ No newline at end of file diff --git a/webroot/AutoSa/UserManage/models.py b/webroot/AutoSa/UserManage/models.py deleted file mode 100644 index 1d17012ae1c1..000000000000 --- a/webroot/AutoSa/UserManage/models.py +++ /dev/null @@ -1,48 +0,0 @@ -from django.db import models - - -class Group(models.Model): - name = models.CharField(max_length=50, unique=True) - - def __unicode__(self): - return self.name - - -class User(models.Model): - username = models.CharField(max_length=50, unique=True) - password = models.CharField(max_length=100) - key_pass = models.CharField(max_length=100) - name = models.CharField(max_length=50) - group = models.ManyToManyField(Group) - is_admin = models.BooleanField(default=False) - is_superuser = models.BooleanField(default=False) - ldap_password = models.CharField(max_length=100, null=False) - email = models.EmailField(max_length=50, null=True, blank=True) - - def __unicode__(self): - return self.username - - -class Logs(models.Model): - user = models.CharField(max_length=50) - host = models.CharField(max_length=20) - logfile = models.CharField(max_length=1000) - finish = models.SmallIntegerField(max_length=4, default=0) - ppid = models.IntegerField() - start_time = models.IntegerField() - end_time = models.IntegerField(default=0) - - def __unicode__(self): - return self.logfile - - -class Pid(models.Model): - """ - ppid : parent pid - cpid: child pid - """ - ppid = models.IntegerField() - cpid = models.IntegerField() - logid = models.IntegerField() - start_time = models.IntegerField() - diff --git a/webroot/AutoSa/UserManage/views.py b/webroot/AutoSa/UserManage/views.py deleted file mode 100644 index 91ea44a218fb..000000000000 --- a/webroot/AutoSa/UserManage/views.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.shortcuts import render - -# Create your views here. diff --git a/webroot/AutoSa/__init__.py b/webroot/AutoSa/__init__.py deleted file mode 100644 index 35b4ebd59f1c..000000000000 --- a/webroot/AutoSa/__init__.py +++ /dev/null @@ -1 +0,0 @@ -#coding:utf-8 diff --git a/webroot/AutoSa/log_handler.py b/webroot/AutoSa/log_handler.py deleted file mode 100755 index f84ab7bbe915..000000000000 --- a/webroot/AutoSa/log_handler.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/python -#coding: utf-8 - -import os -import sys -import time - -cur_dir = os.path.dirname(__file__) -sys.path.append('%s/webroot/AutoSa/' % cur_dir) -os.environ['DJANGO_SETTINGS_MODULE'] = 'AutoSa.settings' - -import django -django.setup() -from UserManage.models import Logs, Pid - - -def log_hanler(logid): - log = Logs.objects.filter(id=logid) - if log: - log = log[0] - filename = log.logfile - if os.path.isfile(filename): - ret1 = os.system('cat %s | grep "DateTime" > %s.his' % (filename, filename)) - ret2 = os.system('cat %s | grep "\[.*@.*\][\$\#]" >> %s.his' % (filename, filename)) - ret3 = os.system('cat %s | grep "EndTime" >> %s.his' % (filename, filename)) - if (ret1 + ret2 + ret3) == 0: - print 'Handler %s ok.' % filename - - -def set_finish(id): - logs = Logs.objects.filter(id=id, finish=0) - if logs: - structtime_start = time.localtime() - timestamp_end = int(time.mktime(structtime_start)) - log = logs[0] - log.finish = 1 - log.end_time = timestamp_end - log.save() - - -def kill_pid(pid): - try: - os.kill(pid, 9) - except OSError: - pass - - -def pid_exist(pid): - pid_dir = "/proc/%s" % pid - if os.path.isdir(pid_dir): - return True - else: - return False - - -def del_pid(pid_id): - pid = Pid.objects.filter(id=pid_id) - if pid: - pid[0].delete() - - -def get_pids(): - pids = [] - pids_obj = Pid.objects.all() - for pid_obj in pids_obj: - pids.append((pid_obj.id, pid_obj.ppid, pid_obj.cpid, pid_obj.logid, pid_obj.start_time)) - return pids - - -def run(): - for pid_id, ppid, cpid, logid, start_time in get_pids(): - if pid_exist(cpid): - if pid_exist(ppid): - structtime_start = time.localtime() - timestamp_end = int(time.mktime(structtime_start)) - if timestamp_end - start_time > 7200: - kill_pid(ppid) - kill_pid(cpid) - del_pid(pid_id) - set_finish(logid) - log_hanler(logid) - else: - kill_pid(cpid) - del_pid(pid_id) - set_finish(logid) - log_hanler(logid) - else: - del_pid(pid_id) - set_finish(logid) - log_hanler(logid) - - -if __name__ == '__main__': - while True: - run() - time.sleep(0.5) diff --git a/webroot/AutoSa/static/css/bootstrap-dialog.css b/webroot/AutoSa/static/css/bootstrap-dialog.css deleted file mode 100644 index 32a001d071a3..000000000000 --- a/webroot/AutoSa/static/css/bootstrap-dialog.css +++ /dev/null @@ -1,120 +0,0 @@ -.bootstrap-dialog { - -} -.bootstrap-dialog .modal-header { - border-top-left-radius: 4px; - border-top-right-radius: 4px; -} -.bootstrap-dialog .bootstrap-dialog-title { - color: #fff; - display: inline-block; -} -.bootstrap-dialog.type-default .bootstrap-dialog-title { - color: #333; -} -.bootstrap-dialog.size-normal .bootstrap-dialog-title { - font-size: 16px; -} -.bootstrap-dialog.size-large .bootstrap-dialog-title { - font-size: 24px; -} -.bootstrap-dialog .bootstrap-dialog-close-button { - float: right; - filter:alpha(opacity=90); - -moz-opacity:0.9; - -khtml-opacity: 0.9; - opacity: 0.9; -} -.bootstrap-dialog.size-normal .bootstrap-dialog-close-button { - font-size: 20px; -} -.bootstrap-dialog.size-large .bootstrap-dialog-close-button { - font-size: 30px; -} -.bootstrap-dialog .bootstrap-dialog-close-button:hover { - cursor: pointer; - filter: alpha(opacity=100); - -moz-opacity: 1; - -khtml-opacity: 1; - opacity: 1; -} -.bootstrap-dialog.size-normal .bootstrap-dialog-message { - font-size: 14px; -} -.bootstrap-dialog.size-large .bootstrap-dialog-message { - font-size: 18px; -} -.bootstrap-dialog.type-default .modal-header { - background-color: #fff; -} -.bootstrap-dialog.type-info .modal-header { - background-color: #5bc0de; -} -.bootstrap-dialog.type-primary .modal-header { - background-color: #428bca; -} -.bootstrap-dialog.type-success .modal-header { - background-color: #5cb85c; -} -.bootstrap-dialog.type-warning .modal-header { - background-color: #f0ad4e; -} -.bootstrap-dialog.type-danger .modal-header { - background-color: #d9534f; -} -.bootstrap-dialog .bootstrap-dialog-button-icon { - margin-right: 3px; -} - -/** - * Icon animation - * Copied from font-awesome: http://fontawesome.io/ - **/ -.icon-spin { - display: inline-block; - -moz-animation: spin 2s infinite linear; - -o-animation: spin 2s infinite linear; - -webkit-animation: spin 2s infinite linear; - animation: spin 2s infinite linear; -} -@-moz-keyframes spin { - 0% { - -moz-transform: rotate(0deg); -} -100% { - -moz-transform: rotate(359deg); -} -} -@-webkit-keyframes spin { - 0% { - -webkit-transform: rotate(0deg); -} -100% { - -webkit-transform: rotate(359deg); -} -} -@-o-keyframes spin { - 0% { - -o-transform: rotate(0deg); -} -100% { - -o-transform: rotate(359deg); -} -} -@-ms-keyframes spin { - 0% { - -ms-transform: rotate(0deg); -} -100% { - -ms-transform: rotate(359deg); -} -} -@keyframes spin { - 0% { - transform: rotate(0deg); -} -100% { - transform: rotate(359deg); -} -} -/** End of icon animation **/ \ No newline at end of file diff --git a/webroot/AutoSa/static/css/bootstrap-theme.css b/webroot/AutoSa/static/css/bootstrap-theme.css deleted file mode 100644 index df2d3d96783c..000000000000 --- a/webroot/AutoSa/static/css/bootstrap-theme.css +++ /dev/null @@ -1,397 +0,0 @@ -/*! - * Bootstrap v3.0.3 (http://getbootstrap.com) - * Copyright 2013 Twitter, Inc. - * Licensed under http://www.apache.org/licenses/LICENSE-2.0 - */ - -.btn-default, -.btn-primary, -.btn-success, -.btn-info, -.btn-warning, -.btn-danger { - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 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, 0.125); - box-shadow: inset 0 3px 5px rgba(0, 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, #ffffff 0%, #e0e0e0 100%); - background-image: linear-gradient(to bottom, #ffffff 0%, #e0e0e0 100%); - background-repeat: repeat-x; - border-color: #dbdbdb; - border-color: #ccc; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.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-primary { - background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%); - background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%); - background-repeat: repeat-x; - border-color: #2b669a; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.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-success { - background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); - background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); - background-repeat: repeat-x; - border-color: #3e8f3e; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.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-warning { - background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); - background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); - background-repeat: repeat-x; - border-color: #e38d13; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.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-danger { - background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); - background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); - background-repeat: repeat-x; - border-color: #b92c28; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.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-info { - background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); - background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); - background-repeat: repeat-x; - border-color: #28a4c9; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.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; -} - -.thumbnail, -.img-thumbnail { - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); - box-shadow: 0 1px 2px rgba(0, 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: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); -} - -.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: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); -} - -.navbar-default { - background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); - background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%); - background-repeat: repeat-x; - border-radius: 4px; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); -} - -.navbar-default .navbar-nav > .active > a { - background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); - background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0); - -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075); -} - -.navbar-brand, -.navbar-nav > li > a { - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); -} - -.navbar-inverse { - background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222222 100%); - background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.navbar-inverse .navbar-nav > .active > a { - background-image: -webkit-linear-gradient(top, #222222 0%, #282828 100%); - background-image: linear-gradient(to bottom, #222222 0%, #282828 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0); - -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25); - box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25); -} - -.navbar-inverse .navbar-brand, -.navbar-inverse .navbar-nav > li > a { - text-shadow: 0 -1px 0 rgba(0, 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, 0.2); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.alert-success { - background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); - background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); - background-repeat: repeat-x; - border-color: #b2dba1; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); -} - -.alert-info { - background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); - background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); - background-repeat: repeat-x; - border-color: #9acfea; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); -} - -.alert-warning { - background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); - background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); - background-repeat: repeat-x; - border-color: #f5e79e; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); -} - -.alert-danger { - background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); - background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); - background-repeat: repeat-x; - border-color: #dca7a7; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); -} - -.progress { - background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); - background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); -} - -.progress-bar { - background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%); - background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); -} - -.progress-bar-success { - background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); - background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); -} - -.progress-bar-info { - background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); - background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); -} - -.progress-bar-warning { - background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); - background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); -} - -.progress-bar-danger { - background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); - background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); -} - -.list-group { - border-radius: 4px; - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); - box-shadow: 0 1px 2px rgba(0, 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: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); - background-repeat: repeat-x; - border-color: #3278b3; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); -} - -.panel { - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.panel-default > .panel-heading { - background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); -} - -.panel-primary > .panel-heading { - background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); - background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); -} - -.panel-success > .panel-heading { - background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); - background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); -} - -.panel-info > .panel-heading { - background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); - background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); -} - -.panel-warning > .panel-heading { - background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); - background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); -} - -.panel-danger > .panel-heading { - background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); - background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); -} - -.well { - background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); - background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); - background-repeat: repeat-x; - border-color: #dcdcdc; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); - -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); - box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); -} \ No newline at end of file diff --git a/webroot/AutoSa/static/css/bootstrap-theme.min.css b/webroot/AutoSa/static/css/bootstrap-theme.min.css deleted file mode 100644 index c7b6d39b4fe2..000000000000 --- a/webroot/AutoSa/static/css/bootstrap-theme.min.css +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap v3.0.3 (http://getbootstrap.com) - * Copyright 2013 Twitter, Inc. - * Licensed under http://www.apache.org/licenses/LICENSE-2.0 - */ - -.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,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,0.125);box-shadow:inset 0 3px 5px rgba(0,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:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe0e0e0',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.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-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);background-repeat:repeat-x;border-color:#2b669a;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff2d6ca2',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.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-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);background-repeat:repeat-x;border-color:#3e8f3e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff419641',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.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-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);background-repeat:repeat-x;border-color:#e38d13;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffeb9316',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.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-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);background-repeat:repeat-x;border-color:#b92c28;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc12e2a',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.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-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);background-repeat:repeat-x;border-color:#28a4c9;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2aabd2',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.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}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,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:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.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:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff8f8f8',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff3f3f3',GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.075);box-shadow:inset 0 3px 9px rgba(0,0,0,0.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:linear-gradient(to bottom,#222 0,#282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff282828',GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.25);box-shadow:inset 0 3px 9px rgba(0,0,0,0.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,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,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;border-color:#b2dba1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffc8e5bc',GradientType=0)}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffb9def0',GradientType=0)}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;border-color:#f5e79e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fff8efc0',GradientType=0)}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;border-color:#dca7a7;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffe7c3c3',GradientType=0)}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff5f5f5',GradientType=0)}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,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:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3278b3',GradientType=0)}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffd0e9c6',GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffc4e3f3',GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fffaf2cc',GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffebcccc',GradientType=0)}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} \ No newline at end of file diff --git a/webroot/AutoSa/static/css/bootstrap.css b/webroot/AutoSa/static/css/bootstrap.css deleted file mode 100644 index 377dff300420..000000000000 --- a/webroot/AutoSa/static/css/bootstrap.css +++ /dev/null @@ -1,7118 +0,0 @@ -/*! - * Bootstrap v3.0.3 (http://getbootstrap.com) - * Copyright 2013 Twitter, Inc. - * Licensed under http://www.apache.org/licenses/LICENSE-2.0 - */ - -/*! normalize.css v2.1.3 | MIT License | git.io/normalize */ - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -nav, -section, -summary { - display: block; -} - -audio, -canvas, -video { - display: inline-block; -} - -audio:not([controls]) { - display: none; - height: 0; -} - -[hidden], -template { - display: none; -} - -html { - font-family: sans-serif; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} - -body { - margin: 0; -} - -a { - background: transparent; -} - -a:focus { - outline: thin dotted; -} - -a:active, -a:hover { - outline: 0; -} - -h1 { - margin: 0.67em 0; - font-size: 2em; -} - -abbr[title] { - border-bottom: 1px dotted; -} - -b, -strong { - font-weight: bold; -} - -dfn { - font-style: italic; -} - -hr { - height: 0; - -moz-box-sizing: content-box; - box-sizing: content-box; -} - -mark { - color: #000; - background: #ff0; -} - -code, -kbd, -pre, -samp { - font-family: monospace, serif; - font-size: 1em; -} - -pre { - white-space: pre-wrap; -} - -q { - quotes: "\201C" "\201D" "\2018" "\2019"; -} - -small { - font-size: 80%; -} - -sub, -sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -img { - border: 0; -} - -svg:not(:root) { - overflow: hidden; -} - -figure { - margin: 0; -} - -fieldset { - padding: 0.35em 0.625em 0.75em; - margin: 0 2px; - border: 1px solid #c0c0c0; -} - -legend { - padding: 0; - border: 0; -} - -button, -input, -select, -textarea { - margin: 0; - font-family: inherit; - font-size: 100%; -} - -button, -input { - line-height: normal; -} - -button, -select { - text-transform: none; -} - -button, -html input[type="button"], -input[type="reset"], -input[type="submit"] { - cursor: pointer; - -webkit-appearance: button; -} - -button[disabled], -html input[disabled] { - cursor: default; -} - -input[type="checkbox"], -input[type="radio"] { - padding: 0; - box-sizing: border-box; -} - -input[type="search"] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield; -} - -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} - -button::-moz-focus-inner, -input::-moz-focus-inner { - padding: 0; - border: 0; -} - -textarea { - overflow: auto; - vertical-align: top; -} - -table { - border-collapse: collapse; - border-spacing: 0; -} - -@media print { - * { - color: #000 !important; - text-shadow: none !important; - background: transparent !important; - box-shadow: none !important; - } - a, - a:visited { - text-decoration: underline; - } - a[href]:after { - content: " (" attr(href) ")"; - } - abbr[title]:after { - content: " (" attr(title) ")"; - } - a[href^="javascript:"]:after, - a[href^="#"]:after { - content: ""; - } - pre, - blockquote { - border: 1px solid #999; - page-break-inside: avoid; - } - thead { - display: table-header-group; - } - tr, - img { - page-break-inside: avoid; - } - img { - max-width: 100% !important; - } - @page { - margin: 2cm .5cm; - } - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - h2, - h3 { - page-break-after: avoid; - } - select { - background: #fff !important; - } - .navbar { - display: none; - } - .table td, - .table th { - background-color: #fff !important; - } - .btn > .caret, - .dropup > .btn > .caret { - border-top-color: #000 !important; - } - .label { - border: 1px solid #000; - } - .table { - border-collapse: collapse !important; - } - .table-bordered th, - .table-bordered td { - border: 1px solid #ddd !important; - } -} - -*, -*:before, -*:after { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -html { - font-size: 62.5%; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} - -body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.428571429; - color: #333333; - background-color: #ffffff; -} - -input, -button, -select, -textarea { - font-family: inherit; - font-size: inherit; - line-height: inherit; -} - -a { - color: #428bca; - text-decoration: none; -} - -a:hover, -a:focus { - color: #2a6496; - text-decoration: underline; -} - -a:focus { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -img { - vertical-align: middle; -} - -.img-responsive { - display: block; - height: auto; - max-width: 100%; -} - -.img-rounded { - border-radius: 6px; -} - -.img-thumbnail { - display: inline-block; - height: auto; - max-width: 100%; - padding: 4px; - line-height: 1.428571429; - background-color: #ffffff; - border: 1px solid #dddddd; - border-radius: 4px; - -webkit-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; -} - -.img-circle { - border-radius: 50%; -} - -hr { - margin-top: 20px; - margin-bottom: 20px; - border: 0; - border-top: 1px solid #eeeeee; -} - -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} - -h1, -h2, -h3, -h4, -h5, -h6, -.h1, -.h2, -.h3, -.h4, -.h5, -.h6 { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-weight: 500; - line-height: 1.1; - color: inherit; -} - -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small, -.h1 small, -.h2 small, -.h3 small, -.h4 small, -.h5 small, -.h6 small, -h1 .small, -h2 .small, -h3 .small, -h4 .small, -h5 .small, -h6 .small, -.h1 .small, -.h2 .small, -.h3 .small, -.h4 .small, -.h5 .small, -.h6 .small { - font-weight: normal; - line-height: 1; - color: #999999; -} - -h1, -h2, -h3 { - margin-top: 20px; - margin-bottom: 10px; -} - -h1 small, -h2 small, -h3 small, -h1 .small, -h2 .small, -h3 .small { - font-size: 65%; -} - -h4, -h5, -h6 { - margin-top: 10px; - margin-bottom: 10px; -} - -h4 small, -h5 small, -h6 small, -h4 .small, -h5 .small, -h6 .small { - font-size: 75%; -} - -h1, -.h1 { - font-size: 36px; -} - -h2, -.h2 { - font-size: 30px; -} - -h3, -.h3 { - font-size: 24px; -} - -h4, -.h4 { - font-size: 18px; -} - -h5, -.h5 { - font-size: 14px; -} - -h6, -.h6 { - font-size: 12px; -} - -p { - margin: 0 0 10px; -} - -.lead { - margin-bottom: 20px; - font-size: 16px; - font-weight: 200; - line-height: 1.4; -} - -@media (min-width: 768px) { - .lead { - font-size: 21px; - } -} - -small, -.small { - font-size: 85%; -} - -cite { - font-style: normal; -} - -.text-muted { - color: #999999; -} - -.text-primary { - color: #428bca; -} - -.text-primary:hover { - color: #3071a9; -} - -.text-warning { - color: #8a6d3b; -} - -.text-warning:hover { - color: #66512c; -} - -.text-danger { - color: #a94442; -} - -.text-danger:hover { - color: #843534; -} - -.text-success { - color: #3c763d; -} - -.text-success:hover { - color: #2b542c; -} - -.text-info { - color: #31708f; -} - -.text-info:hover { - color: #245269; -} - -.text-left { - text-align: left; -} - -.text-right { - text-align: right; -} - -.text-center { - text-align: center; -} - -.page-header { - padding-bottom: 9px; - margin: 40px 0 20px; - border-bottom: 1px solid #eeeeee; -} - -ul, -ol { - margin-top: 0; - margin-bottom: 10px; -} - -ul ul, -ol ul, -ul ol, -ol ol { - margin-bottom: 0; -} - -.list-unstyled { - padding-left: 0; - list-style: none; -} - -.list-inline { - padding-left: 0; - list-style: none; -} - -.list-inline > li { - display: inline-block; - padding-right: 5px; - padding-left: 5px; -} - -.list-inline > li:first-child { - padding-left: 0; -} - -dl { - margin-top: 0; - margin-bottom: 20px; -} - -dt, -dd { - line-height: 1.428571429; -} - -dt { - font-weight: bold; -} - -dd { - margin-left: 0; -} - -@media (min-width: 768px) { - .dl-horizontal dt { - float: left; - width: 160px; - overflow: hidden; - clear: left; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; - } - .dl-horizontal dd { - margin-left: 180px; - } - .dl-horizontal dd:before, - .dl-horizontal dd:after { - display: table; - content: " "; - } - .dl-horizontal dd:after { - clear: both; - } - .dl-horizontal dd:before, - .dl-horizontal dd:after { - display: table; - content: " "; - } - .dl-horizontal dd:after { - clear: both; - } -} - -abbr[title], -abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted #999999; -} - -.initialism { - font-size: 90%; - text-transform: uppercase; -} - -blockquote { - padding: 10px 20px; - margin: 0 0 20px; - border-left: 5px solid #eeeeee; -} - -blockquote p { - font-size: 17.5px; - font-weight: 300; - line-height: 1.25; -} - -blockquote p:last-child { - margin-bottom: 0; -} - -blockquote small, -blockquote .small { - display: block; - line-height: 1.428571429; - color: #999999; -} - -blockquote small:before, -blockquote .small:before { - content: '\2014 \00A0'; -} - -blockquote.pull-right { - padding-right: 15px; - padding-left: 0; - border-right: 5px solid #eeeeee; - border-left: 0; -} - -blockquote.pull-right p, -blockquote.pull-right small, -blockquote.pull-right .small { - text-align: right; -} - -blockquote.pull-right small:before, -blockquote.pull-right .small:before { - content: ''; -} - -blockquote.pull-right small:after, -blockquote.pull-right .small:after { - content: '\00A0 \2014'; -} - -blockquote:before, -blockquote:after { - content: ""; -} - -address { - margin-bottom: 20px; - font-style: normal; - line-height: 1.428571429; -} - -code, -kbd, -pre, -samp { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; -} - -code { - padding: 2px 4px; - font-size: 90%; - color: #c7254e; - white-space: nowrap; - background-color: #f9f2f4; - border-radius: 4px; -} - -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 1.428571429; - color: #333333; - word-break: break-all; - word-wrap: break-word; - background-color: #f5f5f5; - border: 1px solid #cccccc; - border-radius: 4px; -} - -pre code { - padding: 0; - font-size: inherit; - color: inherit; - white-space: pre-wrap; - background-color: transparent; - border-radius: 0; -} - -.pre-scrollable { - max-height: 340px; - overflow-y: scroll; -} - -.container { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} - -.container:before, -.container:after { - display: table; - content: " "; -} - -.container:after { - clear: both; -} - -.container:before, -.container:after { - display: table; - content: " "; -} - -.container:after { - clear: both; -} - -@media (min-width: 768px) { - .container { - width: 750px; - } -} - -@media (min-width: 992px) { - .container { - width: 970px; - } -} - -@media (min-width: 1200px) { - .container { - width: 1170px; - } -} - -.row { - margin-right: -15px; - margin-left: -15px; -} - -.row:before, -.row:after { - display: table; - content: " "; -} - -.row:after { - clear: both; -} - -.row:before, -.row:after { - display: table; - content: " "; -} - -.row:after { - clear: both; -} - -.col-xs-1, -.col-sm-1, -.col-md-1, -.col-lg-1, -.col-xs-2, -.col-sm-2, -.col-md-2, -.col-lg-2, -.col-xs-3, -.col-sm-3, -.col-md-3, -.col-lg-3, -.col-xs-4, -.col-sm-4, -.col-md-4, -.col-lg-4, -.col-xs-5, -.col-sm-5, -.col-md-5, -.col-lg-5, -.col-xs-6, -.col-sm-6, -.col-md-6, -.col-lg-6, -.col-xs-7, -.col-sm-7, -.col-md-7, -.col-lg-7, -.col-xs-8, -.col-sm-8, -.col-md-8, -.col-lg-8, -.col-xs-9, -.col-sm-9, -.col-md-9, -.col-lg-9, -.col-xs-10, -.col-sm-10, -.col-md-10, -.col-lg-10, -.col-xs-11, -.col-sm-11, -.col-md-11, -.col-lg-11, -.col-xs-12, -.col-sm-12, -.col-md-12, -.col-lg-12 { - position: relative; - min-height: 1px; - padding-right: 15px; - padding-left: 15px; -} - -.col-xs-1, -.col-xs-2, -.col-xs-3, -.col-xs-4, -.col-xs-5, -.col-xs-6, -.col-xs-7, -.col-xs-8, -.col-xs-9, -.col-xs-10, -.col-xs-11, -.col-xs-12 { - float: left; -} - -.col-xs-12 { - width: 100%; -} - -.col-xs-11 { - width: 91.66666666666666%; -} - -.col-xs-10 { - width: 83.33333333333334%; -} - -.col-xs-9 { - width: 75%; -} - -.col-xs-8 { - width: 66.66666666666666%; -} - -.col-xs-7 { - width: 58.333333333333336%; -} - -.col-xs-6 { - width: 50%; -} - -.col-xs-5 { - width: 41.66666666666667%; -} - -.col-xs-4 { - width: 33.33333333333333%; -} - -.col-xs-3 { - width: 25%; -} - -.col-xs-2 { - width: 16.666666666666664%; -} - -.col-xs-1 { - width: 8.333333333333332%; -} - -.col-xs-pull-12 { - right: 100%; -} - -.col-xs-pull-11 { - right: 91.66666666666666%; -} - -.col-xs-pull-10 { - right: 83.33333333333334%; -} - -.col-xs-pull-9 { - right: 75%; -} - -.col-xs-pull-8 { - right: 66.66666666666666%; -} - -.col-xs-pull-7 { - right: 58.333333333333336%; -} - -.col-xs-pull-6 { - right: 50%; -} - -.col-xs-pull-5 { - right: 41.66666666666667%; -} - -.col-xs-pull-4 { - right: 33.33333333333333%; -} - -.col-xs-pull-3 { - right: 25%; -} - -.col-xs-pull-2 { - right: 16.666666666666664%; -} - -.col-xs-pull-1 { - right: 8.333333333333332%; -} - -.col-xs-pull-0 { - right: 0; -} - -.col-xs-push-12 { - left: 100%; -} - -.col-xs-push-11 { - left: 91.66666666666666%; -} - -.col-xs-push-10 { - left: 83.33333333333334%; -} - -.col-xs-push-9 { - left: 75%; -} - -.col-xs-push-8 { - left: 66.66666666666666%; -} - -.col-xs-push-7 { - left: 58.333333333333336%; -} - -.col-xs-push-6 { - left: 50%; -} - -.col-xs-push-5 { - left: 41.66666666666667%; -} - -.col-xs-push-4 { - left: 33.33333333333333%; -} - -.col-xs-push-3 { - left: 25%; -} - -.col-xs-push-2 { - left: 16.666666666666664%; -} - -.col-xs-push-1 { - left: 8.333333333333332%; -} - -.col-xs-push-0 { - left: 0; -} - -.col-xs-offset-12 { - margin-left: 100%; -} - -.col-xs-offset-11 { - margin-left: 91.66666666666666%; -} - -.col-xs-offset-10 { - margin-left: 83.33333333333334%; -} - -.col-xs-offset-9 { - margin-left: 75%; -} - -.col-xs-offset-8 { - margin-left: 66.66666666666666%; -} - -.col-xs-offset-7 { - margin-left: 58.333333333333336%; -} - -.col-xs-offset-6 { - margin-left: 50%; -} - -.col-xs-offset-5 { - margin-left: 41.66666666666667%; -} - -.col-xs-offset-4 { - margin-left: 33.33333333333333%; -} - -.col-xs-offset-3 { - margin-left: 25%; -} - -.col-xs-offset-2 { - margin-left: 16.666666666666664%; -} - -.col-xs-offset-1 { - margin-left: 8.333333333333332%; -} - -.col-xs-offset-0 { - margin-left: 0; -} - -@media (min-width: 768px) { - .col-sm-1, - .col-sm-2, - .col-sm-3, - .col-sm-4, - .col-sm-5, - .col-sm-6, - .col-sm-7, - .col-sm-8, - .col-sm-9, - .col-sm-10, - .col-sm-11, - .col-sm-12 { - float: left; - } - .col-sm-12 { - width: 100%; - } - .col-sm-11 { - width: 91.66666666666666%; - } - .col-sm-10 { - width: 83.33333333333334%; - } - .col-sm-9 { - width: 75%; - } - .col-sm-8 { - width: 66.66666666666666%; - } - .col-sm-7 { - width: 58.333333333333336%; - } - .col-sm-6 { - width: 50%; - } - .col-sm-5 { - width: 41.66666666666667%; - } - .col-sm-4 { - width: 33.33333333333333%; - } - .col-sm-3 { - width: 25%; - } - .col-sm-2 { - width: 16.666666666666664%; - } - .col-sm-1 { - width: 8.333333333333332%; - } - .col-sm-pull-12 { - right: 100%; - } - .col-sm-pull-11 { - right: 91.66666666666666%; - } - .col-sm-pull-10 { - right: 83.33333333333334%; - } - .col-sm-pull-9 { - right: 75%; - } - .col-sm-pull-8 { - right: 66.66666666666666%; - } - .col-sm-pull-7 { - right: 58.333333333333336%; - } - .col-sm-pull-6 { - right: 50%; - } - .col-sm-pull-5 { - right: 41.66666666666667%; - } - .col-sm-pull-4 { - right: 33.33333333333333%; - } - .col-sm-pull-3 { - right: 25%; - } - .col-sm-pull-2 { - right: 16.666666666666664%; - } - .col-sm-pull-1 { - right: 8.333333333333332%; - } - .col-sm-pull-0 { - right: 0; - } - .col-sm-push-12 { - left: 100%; - } - .col-sm-push-11 { - left: 91.66666666666666%; - } - .col-sm-push-10 { - left: 83.33333333333334%; - } - .col-sm-push-9 { - left: 75%; - } - .col-sm-push-8 { - left: 66.66666666666666%; - } - .col-sm-push-7 { - left: 58.333333333333336%; - } - .col-sm-push-6 { - left: 50%; - } - .col-sm-push-5 { - left: 41.66666666666667%; - } - .col-sm-push-4 { - left: 33.33333333333333%; - } - .col-sm-push-3 { - left: 25%; - } - .col-sm-push-2 { - left: 16.666666666666664%; - } - .col-sm-push-1 { - left: 8.333333333333332%; - } - .col-sm-push-0 { - left: 0; - } - .col-sm-offset-12 { - margin-left: 100%; - } - .col-sm-offset-11 { - margin-left: 91.66666666666666%; - } - .col-sm-offset-10 { - margin-left: 83.33333333333334%; - } - .col-sm-offset-9 { - margin-left: 75%; - } - .col-sm-offset-8 { - margin-left: 66.66666666666666%; - } - .col-sm-offset-7 { - margin-left: 58.333333333333336%; - } - .col-sm-offset-6 { - margin-left: 50%; - } - .col-sm-offset-5 { - margin-left: 41.66666666666667%; - } - .col-sm-offset-4 { - margin-left: 33.33333333333333%; - } - .col-sm-offset-3 { - margin-left: 25%; - } - .col-sm-offset-2 { - margin-left: 16.666666666666664%; - } - .col-sm-offset-1 { - margin-left: 8.333333333333332%; - } - .col-sm-offset-0 { - margin-left: 0; - } -} - -@media (min-width: 992px) { - .col-md-1, - .col-md-2, - .col-md-3, - .col-md-4, - .col-md-5, - .col-md-6, - .col-md-7, - .col-md-8, - .col-md-9, - .col-md-10, - .col-md-11, - .col-md-12 { - float: left; - } - .col-md-12 { - width: 100%; - } - .col-md-11 { - width: 91.66666666666666%; - } - .col-md-10 { - width: 83.33333333333334%; - } - .col-md-9 { - width: 75%; - } - .col-md-8 { - width: 66.66666666666666%; - } - .col-md-7 { - width: 58.333333333333336%; - } - .col-md-6 { - width: 50%; - } - .col-md-5 { - width: 41.66666666666667%; - } - .col-md-4 { - width: 33.33333333333333%; - } - .col-md-3 { - width: 25%; - } - .col-md-2 { - width: 16.666666666666664%; - } - .col-md-1 { - width: 8.333333333333332%; - } - .col-md-pull-12 { - right: 100%; - } - .col-md-pull-11 { - right: 91.66666666666666%; - } - .col-md-pull-10 { - right: 83.33333333333334%; - } - .col-md-pull-9 { - right: 75%; - } - .col-md-pull-8 { - right: 66.66666666666666%; - } - .col-md-pull-7 { - right: 58.333333333333336%; - } - .col-md-pull-6 { - right: 50%; - } - .col-md-pull-5 { - right: 41.66666666666667%; - } - .col-md-pull-4 { - right: 33.33333333333333%; - } - .col-md-pull-3 { - right: 25%; - } - .col-md-pull-2 { - right: 16.666666666666664%; - } - .col-md-pull-1 { - right: 8.333333333333332%; - } - .col-md-pull-0 { - right: 0; - } - .col-md-push-12 { - left: 100%; - } - .col-md-push-11 { - left: 91.66666666666666%; - } - .col-md-push-10 { - left: 83.33333333333334%; - } - .col-md-push-9 { - left: 75%; - } - .col-md-push-8 { - left: 66.66666666666666%; - } - .col-md-push-7 { - left: 58.333333333333336%; - } - .col-md-push-6 { - left: 50%; - } - .col-md-push-5 { - left: 41.66666666666667%; - } - .col-md-push-4 { - left: 33.33333333333333%; - } - .col-md-push-3 { - left: 25%; - } - .col-md-push-2 { - left: 16.666666666666664%; - } - .col-md-push-1 { - left: 8.333333333333332%; - } - .col-md-push-0 { - left: 0; - } - .col-md-offset-12 { - margin-left: 100%; - } - .col-md-offset-11 { - margin-left: 91.66666666666666%; - } - .col-md-offset-10 { - margin-left: 83.33333333333334%; - } - .col-md-offset-9 { - margin-left: 75%; - } - .col-md-offset-8 { - margin-left: 66.66666666666666%; - } - .col-md-offset-7 { - margin-left: 58.333333333333336%; - } - .col-md-offset-6 { - margin-left: 50%; - } - .col-md-offset-5 { - margin-left: 41.66666666666667%; - } - .col-md-offset-4 { - margin-left: 33.33333333333333%; - } - .col-md-offset-3 { - margin-left: 25%; - } - .col-md-offset-2 { - margin-left: 16.666666666666664%; - } - .col-md-offset-1 { - margin-left: 8.333333333333332%; - } - .col-md-offset-0 { - margin-left: 0; - } -} - -@media (min-width: 1200px) { - .col-lg-1, - .col-lg-2, - .col-lg-3, - .col-lg-4, - .col-lg-5, - .col-lg-6, - .col-lg-7, - .col-lg-8, - .col-lg-9, - .col-lg-10, - .col-lg-11, - .col-lg-12 { - float: left; - } - .col-lg-12 { - width: 100%; - } - .col-lg-11 { - width: 91.66666666666666%; - } - .col-lg-10 { - width: 83.33333333333334%; - } - .col-lg-9 { - width: 75%; - } - .col-lg-8 { - width: 66.66666666666666%; - } - .col-lg-7 { - width: 58.333333333333336%; - } - .col-lg-6 { - width: 50%; - } - .col-lg-5 { - width: 41.66666666666667%; - } - .col-lg-4 { - width: 33.33333333333333%; - } - .col-lg-3 { - width: 25%; - } - .col-lg-2 { - width: 16.666666666666664%; - } - .col-lg-1 { - width: 8.333333333333332%; - } - .col-lg-pull-12 { - right: 100%; - } - .col-lg-pull-11 { - right: 91.66666666666666%; - } - .col-lg-pull-10 { - right: 83.33333333333334%; - } - .col-lg-pull-9 { - right: 75%; - } - .col-lg-pull-8 { - right: 66.66666666666666%; - } - .col-lg-pull-7 { - right: 58.333333333333336%; - } - .col-lg-pull-6 { - right: 50%; - } - .col-lg-pull-5 { - right: 41.66666666666667%; - } - .col-lg-pull-4 { - right: 33.33333333333333%; - } - .col-lg-pull-3 { - right: 25%; - } - .col-lg-pull-2 { - right: 16.666666666666664%; - } - .col-lg-pull-1 { - right: 8.333333333333332%; - } - .col-lg-pull-0 { - right: 0; - } - .col-lg-push-12 { - left: 100%; - } - .col-lg-push-11 { - left: 91.66666666666666%; - } - .col-lg-push-10 { - left: 83.33333333333334%; - } - .col-lg-push-9 { - left: 75%; - } - .col-lg-push-8 { - left: 66.66666666666666%; - } - .col-lg-push-7 { - left: 58.333333333333336%; - } - .col-lg-push-6 { - left: 50%; - } - .col-lg-push-5 { - left: 41.66666666666667%; - } - .col-lg-push-4 { - left: 33.33333333333333%; - } - .col-lg-push-3 { - left: 25%; - } - .col-lg-push-2 { - left: 16.666666666666664%; - } - .col-lg-push-1 { - left: 8.333333333333332%; - } - .col-lg-push-0 { - left: 0; - } - .col-lg-offset-12 { - margin-left: 100%; - } - .col-lg-offset-11 { - margin-left: 91.66666666666666%; - } - .col-lg-offset-10 { - margin-left: 83.33333333333334%; - } - .col-lg-offset-9 { - margin-left: 75%; - } - .col-lg-offset-8 { - margin-left: 66.66666666666666%; - } - .col-lg-offset-7 { - margin-left: 58.333333333333336%; - } - .col-lg-offset-6 { - margin-left: 50%; - } - .col-lg-offset-5 { - margin-left: 41.66666666666667%; - } - .col-lg-offset-4 { - margin-left: 33.33333333333333%; - } - .col-lg-offset-3 { - margin-left: 25%; - } - .col-lg-offset-2 { - margin-left: 16.666666666666664%; - } - .col-lg-offset-1 { - margin-left: 8.333333333333332%; - } - .col-lg-offset-0 { - margin-left: 0; - } -} - -table { - max-width: 100%; - background-color: transparent; -} - -th { - text-align: left; -} - -.table { - width: 100%; - margin-bottom: 20px; -} - -.table > thead > tr > th, -.table > tbody > tr > th, -.table > tfoot > tr > th, -.table > thead > tr > td, -.table > tbody > tr > td, -.table > tfoot > tr > td { - padding: 8px; - line-height: 1.428571429; - vertical-align: top; - border-top: 1px solid #dddddd; -} - -.table > thead > tr > th { - vertical-align: bottom; - border-bottom: 2px solid #dddddd; -} - -.table > caption + thead > tr:first-child > th, -.table > colgroup + thead > tr:first-child > th, -.table > thead:first-child > tr:first-child > th, -.table > caption + thead > tr:first-child > td, -.table > colgroup + thead > tr:first-child > td, -.table > thead:first-child > tr:first-child > td { - border-top: 0; -} - -.table > tbody + tbody { - border-top: 2px solid #dddddd; -} - -.table .table { - background-color: #ffffff; -} - -.table-condensed > thead > tr > th, -.table-condensed > tbody > tr > th, -.table-condensed > tfoot > tr > th, -.table-condensed > thead > tr > td, -.table-condensed > tbody > tr > td, -.table-condensed > tfoot > tr > td { - padding: 5px; -} - -.table-bordered { - border: 1px solid #dddddd; -} - -.table-bordered > thead > tr > th, -.table-bordered > tbody > tr > th, -.table-bordered > tfoot > tr > th, -.table-bordered > thead > tr > td, -.table-bordered > tbody > tr > td, -.table-bordered > tfoot > tr > td { - border: 1px solid #dddddd; -} - -.table-bordered > thead > tr > th, -.table-bordered > thead > tr > td { - border-bottom-width: 2px; -} - -.table-striped > tbody > tr:nth-child(odd) > td, -.table-striped > tbody > tr:nth-child(odd) > th { - background-color: #f9f9f9; -} - -.table-hover > tbody > tr:hover > td, -.table-hover > tbody > tr:hover > th { - background-color: #f5f5f5; -} - -table col[class*="col-"] { - position: static; - display: table-column; - float: none; -} - -table td[class*="col-"], -table th[class*="col-"] { - display: table-cell; - float: none; -} - -.table > thead > tr > .active, -.table > tbody > tr > .active, -.table > tfoot > tr > .active, -.table > thead > .active > td, -.table > tbody > .active > td, -.table > tfoot > .active > td, -.table > thead > .active > th, -.table > tbody > .active > th, -.table > tfoot > .active > th { - background-color: #f5f5f5; -} - -.table-hover > tbody > tr > .active:hover, -.table-hover > tbody > .active:hover > td, -.table-hover > tbody > .active:hover > th { - background-color: #e8e8e8; -} - -.table > thead > tr > .success, -.table > tbody > tr > .success, -.table > tfoot > tr > .success, -.table > thead > .success > td, -.table > tbody > .success > td, -.table > tfoot > .success > td, -.table > thead > .success > th, -.table > tbody > .success > th, -.table > tfoot > .success > th { - background-color: #dff0d8; -} - -.table-hover > tbody > tr > .success:hover, -.table-hover > tbody > .success:hover > td, -.table-hover > tbody > .success:hover > th { - background-color: #d0e9c6; -} - -.table > thead > tr > .danger, -.table > tbody > tr > .danger, -.table > tfoot > tr > .danger, -.table > thead > .danger > td, -.table > tbody > .danger > td, -.table > tfoot > .danger > td, -.table > thead > .danger > th, -.table > tbody > .danger > th, -.table > tfoot > .danger > th { - background-color: #f2dede; -} - -.table-hover > tbody > tr > .danger:hover, -.table-hover > tbody > .danger:hover > td, -.table-hover > tbody > .danger:hover > th { - background-color: #ebcccc; -} - -.table > thead > tr > .warning, -.table > tbody > tr > .warning, -.table > tfoot > tr > .warning, -.table > thead > .warning > td, -.table > tbody > .warning > td, -.table > tfoot > .warning > td, -.table > thead > .warning > th, -.table > tbody > .warning > th, -.table > tfoot > .warning > th { - background-color: #fcf8e3; -} - -.table-hover > tbody > tr > .warning:hover, -.table-hover > tbody > .warning:hover > td, -.table-hover > tbody > .warning:hover > th { - background-color: #faf2cc; -} - -@media (max-width: 767px) { - .table-responsive { - width: 100%; - margin-bottom: 15px; - overflow-x: scroll; - overflow-y: hidden; - border: 1px solid #dddddd; - -ms-overflow-style: -ms-autohiding-scrollbar; - -webkit-overflow-scrolling: touch; - } - .table-responsive > .table { - margin-bottom: 0; - } - .table-responsive > .table > thead > tr > th, - .table-responsive > .table > tbody > tr > th, - .table-responsive > .table > tfoot > tr > th, - .table-responsive > .table > thead > tr > td, - .table-responsive > .table > tbody > tr > td, - .table-responsive > .table > tfoot > tr > td { - white-space: nowrap; - } - .table-responsive > .table-bordered { - border: 0; - } - .table-responsive > .table-bordered > thead > tr > th:first-child, - .table-responsive > .table-bordered > tbody > tr > th:first-child, - .table-responsive > .table-bordered > tfoot > tr > th:first-child, - .table-responsive > .table-bordered > thead > tr > td:first-child, - .table-responsive > .table-bordered > tbody > tr > td:first-child, - .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; - } - .table-responsive > .table-bordered > thead > tr > th:last-child, - .table-responsive > .table-bordered > tbody > tr > th:last-child, - .table-responsive > .table-bordered > tfoot > tr > th:last-child, - .table-responsive > .table-bordered > thead > tr > td:last-child, - .table-responsive > .table-bordered > tbody > tr > td:last-child, - .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; - } - .table-responsive > .table-bordered > tbody > tr:last-child > th, - .table-responsive > .table-bordered > tfoot > tr:last-child > th, - .table-responsive > .table-bordered > tbody > tr:last-child > td, - .table-responsive > .table-bordered > tfoot > tr:last-child > td { - border-bottom: 0; - } -} - -fieldset { - padding: 0; - margin: 0; - border: 0; -} - -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: inherit; - color: #333333; - border: 0; - border-bottom: 1px solid #e5e5e5; -} - -label { - display: inline-block; - margin-bottom: 5px; - font-weight: bold; -} - -input[type="search"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} - -input[type="radio"], -input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; - /* IE8-9 */ - - line-height: normal; -} - -input[type="file"] { - display: block; -} - -select[multiple], -select[size] { - height: auto; -} - -select optgroup { - font-family: inherit; - font-size: inherit; - font-style: inherit; -} - -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -input[type="number"]::-webkit-outer-spin-button, -input[type="number"]::-webkit-inner-spin-button { - height: auto; -} - -output { - display: block; - padding-top: 7px; - font-size: 14px; - line-height: 1.428571429; - color: #555555; - vertical-align: middle; -} - -.form-control { - display: block; - width: 100%; - height: 34px; - padding: 6px 12px; - font-size: 14px; - line-height: 1.428571429; - color: #555555; - vertical-align: middle; - background-color: #ffffff; - background-image: none; - border: 1px solid #cccccc; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; - transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; -} - -.form-control:focus { - border-color: #66afe9; - outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); -} - -.form-control:-moz-placeholder { - color: #999999; -} - -.form-control::-moz-placeholder { - color: #999999; - opacity: 1; -} - -.form-control:-ms-input-placeholder { - color: #999999; -} - -.form-control::-webkit-input-placeholder { - color: #999999; -} - -.form-control[disabled], -.form-control[readonly], -fieldset[disabled] .form-control { - cursor: not-allowed; - background-color: #eeeeee; -} - -textarea.form-control { - height: auto; -} - -.form-group { - margin-bottom: 15px; -} - -.radio, -.checkbox { - display: block; - min-height: 20px; - padding-left: 20px; - margin-top: 10px; - margin-bottom: 10px; - vertical-align: middle; -} - -.radio label, -.checkbox label { - display: inline; - margin-bottom: 0; - font-weight: normal; - cursor: pointer; -} - -.radio input[type="radio"], -.radio-inline input[type="radio"], -.checkbox input[type="checkbox"], -.checkbox-inline input[type="checkbox"] { - float: left; - margin-left: -20px; -} - -.radio + .radio, -.checkbox + .checkbox { - margin-top: -5px; -} - -.radio-inline, -.checkbox-inline { - display: inline-block; - padding-left: 20px; - margin-bottom: 0; - font-weight: normal; - vertical-align: middle; - cursor: pointer; -} - -.radio-inline + .radio-inline, -.checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; -} - -input[type="radio"][disabled], -input[type="checkbox"][disabled], -.radio[disabled], -.radio-inline[disabled], -.checkbox[disabled], -.checkbox-inline[disabled], -fieldset[disabled] input[type="radio"], -fieldset[disabled] input[type="checkbox"], -fieldset[disabled] .radio, -fieldset[disabled] .radio-inline, -fieldset[disabled] .checkbox, -fieldset[disabled] .checkbox-inline { - cursor: not-allowed; -} - -.input-sm { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} - -select.input-sm { - height: 30px; - line-height: 30px; -} - -textarea.input-sm { - height: auto; -} - -.input-lg { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; -} - -select.input-lg { - height: 46px; - line-height: 46px; -} - -textarea.input-lg { - height: auto; -} - -.has-warning .help-block, -.has-warning .control-label, -.has-warning .radio, -.has-warning .checkbox, -.has-warning .radio-inline, -.has-warning .checkbox-inline { - color: #8a6d3b; -} - -.has-warning .form-control { - border-color: #8a6d3b; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.has-warning .form-control:focus { - border-color: #66512c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; -} - -.has-warning .input-group-addon { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #8a6d3b; -} - -.has-error .help-block, -.has-error .control-label, -.has-error .radio, -.has-error .checkbox, -.has-error .radio-inline, -.has-error .checkbox-inline { - color: #a94442; -} - -.has-error .form-control { - border-color: #a94442; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.has-error .form-control:focus { - border-color: #843534; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; -} - -.has-error .input-group-addon { - color: #a94442; - background-color: #f2dede; - border-color: #a94442; -} - -.has-success .help-block, -.has-success .control-label, -.has-success .radio, -.has-success .checkbox, -.has-success .radio-inline, -.has-success .checkbox-inline { - color: #3c763d; -} - -.has-success .form-control { - border-color: #3c763d; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.has-success .form-control:focus { - border-color: #2b542c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; -} - -.has-success .input-group-addon { - color: #3c763d; - background-color: #dff0d8; - border-color: #3c763d; -} - -.form-control-static { - margin-bottom: 0; -} - -.help-block { - display: block; - margin-top: 5px; - margin-bottom: 10px; - color: #737373; -} - -@media (min-width: 768px) { - .form-inline .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .form-control { - display: inline-block; - } - .form-inline select.form-control { - width: auto; - } - .form-inline .radio, - .form-inline .checkbox { - display: inline-block; - padding-left: 0; - margin-top: 0; - margin-bottom: 0; - } - .form-inline .radio input[type="radio"], - .form-inline .checkbox input[type="checkbox"] { - float: none; - margin-left: 0; - } -} - -.form-horizontal .control-label, -.form-horizontal .radio, -.form-horizontal .checkbox, -.form-horizontal .radio-inline, -.form-horizontal .checkbox-inline { - padding-top: 7px; - margin-top: 0; - margin-bottom: 0; -} - -.form-horizontal .radio, -.form-horizontal .checkbox { - min-height: 27px; -} - -.form-horizontal .form-group { - margin-right: -15px; - margin-left: -15px; -} - -.form-horizontal .form-group:before, -.form-horizontal .form-group:after { - display: table; - content: " "; -} - -.form-horizontal .form-group:after { - clear: both; -} - -.form-horizontal .form-group:before, -.form-horizontal .form-group:after { - display: table; - content: " "; -} - -.form-horizontal .form-group:after { - clear: both; -} - -.form-horizontal .form-control-static { - padding-top: 7px; -} - -@media (min-width: 768px) { - .form-horizontal .control-label { - text-align: right; - } -} - -.btn { - display: inline-block; - padding: 6px 12px; - margin-bottom: 0; - font-size: 14px; - font-weight: normal; - line-height: 1.428571429; - text-align: center; - white-space: nowrap; - vertical-align: middle; - cursor: pointer; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; -} - -.btn:focus { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} - -.btn:hover, -.btn:focus { - color: #333333; - text-decoration: none; -} - -.btn:active, -.btn.active { - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); -} - -.btn.disabled, -.btn[disabled], -fieldset[disabled] .btn { - pointer-events: none; - cursor: not-allowed; - opacity: 0.65; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - box-shadow: none; -} - -.btn-default { - color: #333333; - background-color: #ffffff; - border-color: #cccccc; -} - -.btn-default:hover, -.btn-default:focus, -.btn-default:active, -.btn-default.active, -.open .dropdown-toggle.btn-default { - color: #333333; - background-color: #ebebeb; - border-color: #adadad; -} - -.btn-default:active, -.btn-default.active, -.open .dropdown-toggle.btn-default { - background-image: none; -} - -.btn-default.disabled, -.btn-default[disabled], -fieldset[disabled] .btn-default, -.btn-default.disabled:hover, -.btn-default[disabled]:hover, -fieldset[disabled] .btn-default:hover, -.btn-default.disabled:focus, -.btn-default[disabled]:focus, -fieldset[disabled] .btn-default:focus, -.btn-default.disabled:active, -.btn-default[disabled]:active, -fieldset[disabled] .btn-default:active, -.btn-default.disabled.active, -.btn-default[disabled].active, -fieldset[disabled] .btn-default.active { - background-color: #ffffff; - border-color: #cccccc; -} - -.btn-default .badge { - color: #ffffff; - background-color: #fff; -} - -.btn-primary { - color: #ffffff; - background-color: #428bca; - border-color: #357ebd; -} - -.btn-primary:hover, -.btn-primary:focus, -.btn-primary:active, -.btn-primary.active, -.open .dropdown-toggle.btn-primary { - color: #ffffff; - background-color: #3276b1; - border-color: #285e8e; -} - -.btn-primary:active, -.btn-primary.active, -.open .dropdown-toggle.btn-primary { - background-image: none; -} - -.btn-primary.disabled, -.btn-primary[disabled], -fieldset[disabled] .btn-primary, -.btn-primary.disabled:hover, -.btn-primary[disabled]:hover, -fieldset[disabled] .btn-primary:hover, -.btn-primary.disabled:focus, -.btn-primary[disabled]:focus, -fieldset[disabled] .btn-primary:focus, -.btn-primary.disabled:active, -.btn-primary[disabled]:active, -fieldset[disabled] .btn-primary:active, -.btn-primary.disabled.active, -.btn-primary[disabled].active, -fieldset[disabled] .btn-primary.active { - background-color: #428bca; - border-color: #357ebd; -} - -.btn-primary .badge { - color: #428bca; - background-color: #fff; -} - -.btn-warning { - color: #ffffff; - background-color: #f0ad4e; - border-color: #eea236; -} - -.btn-warning:hover, -.btn-warning:focus, -.btn-warning:active, -.btn-warning.active, -.open .dropdown-toggle.btn-warning { - color: #ffffff; - background-color: #ed9c28; - border-color: #d58512; -} - -.btn-warning:active, -.btn-warning.active, -.open .dropdown-toggle.btn-warning { - background-image: none; -} - -.btn-warning.disabled, -.btn-warning[disabled], -fieldset[disabled] .btn-warning, -.btn-warning.disabled:hover, -.btn-warning[disabled]:hover, -fieldset[disabled] .btn-warning:hover, -.btn-warning.disabled:focus, -.btn-warning[disabled]:focus, -fieldset[disabled] .btn-warning:focus, -.btn-warning.disabled:active, -.btn-warning[disabled]:active, -fieldset[disabled] .btn-warning:active, -.btn-warning.disabled.active, -.btn-warning[disabled].active, -fieldset[disabled] .btn-warning.active { - background-color: #f0ad4e; - border-color: #eea236; -} - -.btn-warning .badge { - color: #f0ad4e; - background-color: #fff; -} - -.btn-danger { - color: #ffffff; - background-color: #d9534f; - border-color: #d43f3a; -} - -.btn-danger:hover, -.btn-danger:focus, -.btn-danger:active, -.btn-danger.active, -.open .dropdown-toggle.btn-danger { - color: #ffffff; - background-color: #d2322d; - border-color: #ac2925; -} - -.btn-danger:active, -.btn-danger.active, -.open .dropdown-toggle.btn-danger { - background-image: none; -} - -.btn-danger.disabled, -.btn-danger[disabled], -fieldset[disabled] .btn-danger, -.btn-danger.disabled:hover, -.btn-danger[disabled]:hover, -fieldset[disabled] .btn-danger:hover, -.btn-danger.disabled:focus, -.btn-danger[disabled]:focus, -fieldset[disabled] .btn-danger:focus, -.btn-danger.disabled:active, -.btn-danger[disabled]:active, -fieldset[disabled] .btn-danger:active, -.btn-danger.disabled.active, -.btn-danger[disabled].active, -fieldset[disabled] .btn-danger.active { - background-color: #d9534f; - border-color: #d43f3a; -} - -.btn-danger .badge { - color: #d9534f; - background-color: #fff; -} - -.btn-success { - color: #ffffff; - background-color: #5cb85c; - border-color: #4cae4c; -} - -.btn-success:hover, -.btn-success:focus, -.btn-success:active, -.btn-success.active, -.open .dropdown-toggle.btn-success { - color: #ffffff; - background-color: #47a447; - border-color: #398439; -} - -.btn-success:active, -.btn-success.active, -.open .dropdown-toggle.btn-success { - background-image: none; -} - -.btn-success.disabled, -.btn-success[disabled], -fieldset[disabled] .btn-success, -.btn-success.disabled:hover, -.btn-success[disabled]:hover, -fieldset[disabled] .btn-success:hover, -.btn-success.disabled:focus, -.btn-success[disabled]:focus, -fieldset[disabled] .btn-success:focus, -.btn-success.disabled:active, -.btn-success[disabled]:active, -fieldset[disabled] .btn-success:active, -.btn-success.disabled.active, -.btn-success[disabled].active, -fieldset[disabled] .btn-success.active { - background-color: #5cb85c; - border-color: #4cae4c; -} - -.btn-success .badge { - color: #5cb85c; - background-color: #fff; -} - -.btn-info { - color: #ffffff; - background-color: #5bc0de; - border-color: #46b8da; -} - -.btn-info:hover, -.btn-info:focus, -.btn-info:active, -.btn-info.active, -.open .dropdown-toggle.btn-info { - color: #ffffff; - background-color: #39b3d7; - border-color: #269abc; -} - -.btn-info:active, -.btn-info.active, -.open .dropdown-toggle.btn-info { - background-image: none; -} - -.btn-info.disabled, -.btn-info[disabled], -fieldset[disabled] .btn-info, -.btn-info.disabled:hover, -.btn-info[disabled]:hover, -fieldset[disabled] .btn-info:hover, -.btn-info.disabled:focus, -.btn-info[disabled]:focus, -fieldset[disabled] .btn-info:focus, -.btn-info.disabled:active, -.btn-info[disabled]:active, -fieldset[disabled] .btn-info:active, -.btn-info.disabled.active, -.btn-info[disabled].active, -fieldset[disabled] .btn-info.active { - background-color: #5bc0de; - border-color: #46b8da; -} - -.btn-info .badge { - color: #5bc0de; - background-color: #fff; -} - -.btn-link { - font-weight: normal; - color: #428bca; - cursor: pointer; - border-radius: 0; -} - -.btn-link, -.btn-link:active, -.btn-link[disabled], -fieldset[disabled] .btn-link { - background-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; -} - -.btn-link, -.btn-link:hover, -.btn-link:focus, -.btn-link:active { - border-color: transparent; -} - -.btn-link:hover, -.btn-link:focus { - color: #2a6496; - text-decoration: underline; - background-color: transparent; -} - -.btn-link[disabled]:hover, -fieldset[disabled] .btn-link:hover, -.btn-link[disabled]:focus, -fieldset[disabled] .btn-link:focus { - color: #999999; - text-decoration: none; -} - -.btn-lg { - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; -} - -.btn-sm { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} - -.btn-xs { - padding: 1px 5px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} - -.btn-block { - display: block; - width: 100%; - padding-right: 0; - padding-left: 0; -} - -.btn-block + .btn-block { - margin-top: 5px; -} - -input[type="submit"].btn-block, -input[type="reset"].btn-block, -input[type="button"].btn-block { - width: 100%; -} - -.fade { - opacity: 0; - -webkit-transition: opacity 0.15s linear; - transition: opacity 0.15s linear; -} - -.fade.in { - opacity: 1; -} - -.collapse { - display: none; -} - -.collapse.in { - display: block; -} - -.collapsing { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition: height 0.35s ease; - transition: height 0.35s ease; -} - -@font-face { - font-family: 'Glyphicons Halflings'; - src: url('../fonts/glyphicons-halflings-regular.eot'); - src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg'); -} - -.glyphicon { - position: relative; - top: 1px; - display: inline-block; - font-family: 'Glyphicons Halflings'; - -webkit-font-smoothing: antialiased; - font-style: normal; - font-weight: normal; - line-height: 1; - -moz-osx-font-smoothing: grayscale; -} - -.glyphicon:empty { - width: 1em; -} - -.glyphicon-asterisk:before { - content: "\2a"; -} - -.glyphicon-plus:before { - content: "\2b"; -} - -.glyphicon-euro:before { - content: "\20ac"; -} - -.glyphicon-minus:before { - content: "\2212"; -} - -.glyphicon-cloud:before { - content: "\2601"; -} - -.glyphicon-envelope:before { - content: "\2709"; -} - -.glyphicon-pencil:before { - content: "\270f"; -} - -.glyphicon-glass:before { - content: "\e001"; -} - -.glyphicon-music:before { - content: "\e002"; -} - -.glyphicon-search:before { - content: "\e003"; -} - -.glyphicon-heart:before { - content: "\e005"; -} - -.glyphicon-star:before { - content: "\e006"; -} - -.glyphicon-star-empty:before { - content: "\e007"; -} - -.glyphicon-user:before { - content: "\e008"; -} - -.glyphicon-film:before { - content: "\e009"; -} - -.glyphicon-th-large:before { - content: "\e010"; -} - -.glyphicon-th:before { - content: "\e011"; -} - -.glyphicon-th-list:before { - content: "\e012"; -} - -.glyphicon-ok:before { - content: "\e013"; -} - -.glyphicon-remove:before { - content: "\e014"; -} - -.glyphicon-zoom-in:before { - content: "\e015"; -} - -.glyphicon-zoom-out:before { - content: "\e016"; -} - -.glyphicon-off:before { - content: "\e017"; -} - -.glyphicon-signal:before { - content: "\e018"; -} - -.glyphicon-cog:before { - content: "\e019"; -} - -.glyphicon-trash:before { - content: "\e020"; -} - -.glyphicon-home:before { - content: "\e021"; -} - -.glyphicon-file:before { - content: "\e022"; -} - -.glyphicon-time:before { - content: "\e023"; -} - -.glyphicon-road:before { - content: "\e024"; -} - -.glyphicon-download-alt:before { - content: "\e025"; -} - -.glyphicon-download:before { - content: "\e026"; -} - -.glyphicon-upload:before { - content: "\e027"; -} - -.glyphicon-inbox:before { - content: "\e028"; -} - -.glyphicon-play-circle:before { - content: "\e029"; -} - -.glyphicon-repeat:before { - content: "\e030"; -} - -.glyphicon-refresh:before { - content: "\e031"; -} - -.glyphicon-list-alt:before { - content: "\e032"; -} - -.glyphicon-lock:before { - content: "\e033"; -} - -.glyphicon-flag:before { - content: "\e034"; -} - -.glyphicon-headphones:before { - content: "\e035"; -} - -.glyphicon-volume-off:before { - content: "\e036"; -} - -.glyphicon-volume-down:before { - content: "\e037"; -} - -.glyphicon-volume-up:before { - content: "\e038"; -} - -.glyphicon-qrcode:before { - content: "\e039"; -} - -.glyphicon-barcode:before { - content: "\e040"; -} - -.glyphicon-tag:before { - content: "\e041"; -} - -.glyphicon-tags:before { - content: "\e042"; -} - -.glyphicon-book:before { - content: "\e043"; -} - -.glyphicon-bookmark:before { - content: "\e044"; -} - -.glyphicon-print:before { - content: "\e045"; -} - -.glyphicon-camera:before { - content: "\e046"; -} - -.glyphicon-font:before { - content: "\e047"; -} - -.glyphicon-bold:before { - content: "\e048"; -} - -.glyphicon-italic:before { - content: "\e049"; -} - -.glyphicon-text-height:before { - content: "\e050"; -} - -.glyphicon-text-width:before { - content: "\e051"; -} - -.glyphicon-align-left:before { - content: "\e052"; -} - -.glyphicon-align-center:before { - content: "\e053"; -} - -.glyphicon-align-right:before { - content: "\e054"; -} - -.glyphicon-align-justify:before { - content: "\e055"; -} - -.glyphicon-list:before { - content: "\e056"; -} - -.glyphicon-indent-left:before { - content: "\e057"; -} - -.glyphicon-indent-right:before { - content: "\e058"; -} - -.glyphicon-facetime-video:before { - content: "\e059"; -} - -.glyphicon-picture:before { - content: "\e060"; -} - -.glyphicon-map-marker:before { - content: "\e062"; -} - -.glyphicon-adjust:before { - content: "\e063"; -} - -.glyphicon-tint:before { - content: "\e064"; -} - -.glyphicon-edit:before { - content: "\e065"; -} - -.glyphicon-share:before { - content: "\e066"; -} - -.glyphicon-check:before { - content: "\e067"; -} - -.glyphicon-move:before { - content: "\e068"; -} - -.glyphicon-step-backward:before { - content: "\e069"; -} - -.glyphicon-fast-backward:before { - content: "\e070"; -} - -.glyphicon-backward:before { - content: "\e071"; -} - -.glyphicon-play:before { - content: "\e072"; -} - -.glyphicon-pause:before { - content: "\e073"; -} - -.glyphicon-stop:before { - content: "\e074"; -} - -.glyphicon-forward:before { - content: "\e075"; -} - -.glyphicon-fast-forward:before { - content: "\e076"; -} - -.glyphicon-step-forward:before { - content: "\e077"; -} - -.glyphicon-eject:before { - content: "\e078"; -} - -.glyphicon-chevron-left:before { - content: "\e079"; -} - -.glyphicon-chevron-right:before { - content: "\e080"; -} - -.glyphicon-plus-sign:before { - content: "\e081"; -} - -.glyphicon-minus-sign:before { - content: "\e082"; -} - -.glyphicon-remove-sign:before { - content: "\e083"; -} - -.glyphicon-ok-sign:before { - content: "\e084"; -} - -.glyphicon-question-sign:before { - content: "\e085"; -} - -.glyphicon-info-sign:before { - content: "\e086"; -} - -.glyphicon-screenshot:before { - content: "\e087"; -} - -.glyphicon-remove-circle:before { - content: "\e088"; -} - -.glyphicon-ok-circle:before { - content: "\e089"; -} - -.glyphicon-ban-circle:before { - content: "\e090"; -} - -.glyphicon-arrow-left:before { - content: "\e091"; -} - -.glyphicon-arrow-right:before { - content: "\e092"; -} - -.glyphicon-arrow-up:before { - content: "\e093"; -} - -.glyphicon-arrow-down:before { - content: "\e094"; -} - -.glyphicon-share-alt:before { - content: "\e095"; -} - -.glyphicon-resize-full:before { - content: "\e096"; -} - -.glyphicon-resize-small:before { - content: "\e097"; -} - -.glyphicon-exclamation-sign:before { - content: "\e101"; -} - -.glyphicon-gift:before { - content: "\e102"; -} - -.glyphicon-leaf:before { - content: "\e103"; -} - -.glyphicon-fire:before { - content: "\e104"; -} - -.glyphicon-eye-open:before { - content: "\e105"; -} - -.glyphicon-eye-close:before { - content: "\e106"; -} - -.glyphicon-warning-sign:before { - content: "\e107"; -} - -.glyphicon-plane:before { - content: "\e108"; -} - -.glyphicon-calendar:before { - content: "\e109"; -} - -.glyphicon-random:before { - content: "\e110"; -} - -.glyphicon-comment:before { - content: "\e111"; -} - -.glyphicon-magnet:before { - content: "\e112"; -} - -.glyphicon-chevron-up:before { - content: "\e113"; -} - -.glyphicon-chevron-down:before { - content: "\e114"; -} - -.glyphicon-retweet:before { - content: "\e115"; -} - -.glyphicon-shopping-cart:before { - content: "\e116"; -} - -.glyphicon-folder-close:before { - content: "\e117"; -} - -.glyphicon-folder-open:before { - content: "\e118"; -} - -.glyphicon-resize-vertical:before { - content: "\e119"; -} - -.glyphicon-resize-horizontal:before { - content: "\e120"; -} - -.glyphicon-hdd:before { - content: "\e121"; -} - -.glyphicon-bullhorn:before { - content: "\e122"; -} - -.glyphicon-bell:before { - content: "\e123"; -} - -.glyphicon-certificate:before { - content: "\e124"; -} - -.glyphicon-thumbs-up:before { - content: "\e125"; -} - -.glyphicon-thumbs-down:before { - content: "\e126"; -} - -.glyphicon-hand-right:before { - content: "\e127"; -} - -.glyphicon-hand-left:before { - content: "\e128"; -} - -.glyphicon-hand-up:before { - content: "\e129"; -} - -.glyphicon-hand-down:before { - content: "\e130"; -} - -.glyphicon-circle-arrow-right:before { - content: "\e131"; -} - -.glyphicon-circle-arrow-left:before { - content: "\e132"; -} - -.glyphicon-circle-arrow-up:before { - content: "\e133"; -} - -.glyphicon-circle-arrow-down:before { - content: "\e134"; -} - -.glyphicon-globe:before { - content: "\e135"; -} - -.glyphicon-wrench:before { - content: "\e136"; -} - -.glyphicon-tasks:before { - content: "\e137"; -} - -.glyphicon-filter:before { - content: "\e138"; -} - -.glyphicon-briefcase:before { - content: "\e139"; -} - -.glyphicon-fullscreen:before { - content: "\e140"; -} - -.glyphicon-dashboard:before { - content: "\e141"; -} - -.glyphicon-paperclip:before { - content: "\e142"; -} - -.glyphicon-heart-empty:before { - content: "\e143"; -} - -.glyphicon-link:before { - content: "\e144"; -} - -.glyphicon-phone:before { - content: "\e145"; -} - -.glyphicon-pushpin:before { - content: "\e146"; -} - -.glyphicon-usd:before { - content: "\e148"; -} - -.glyphicon-gbp:before { - content: "\e149"; -} - -.glyphicon-sort:before { - content: "\e150"; -} - -.glyphicon-sort-by-alphabet:before { - content: "\e151"; -} - -.glyphicon-sort-by-alphabet-alt:before { - content: "\e152"; -} - -.glyphicon-sort-by-order:before { - content: "\e153"; -} - -.glyphicon-sort-by-order-alt:before { - content: "\e154"; -} - -.glyphicon-sort-by-attributes:before { - content: "\e155"; -} - -.glyphicon-sort-by-attributes-alt:before { - content: "\e156"; -} - -.glyphicon-unchecked:before { - content: "\e157"; -} - -.glyphicon-expand:before { - content: "\e158"; -} - -.glyphicon-collapse-down:before { - content: "\e159"; -} - -.glyphicon-collapse-up:before { - content: "\e160"; -} - -.glyphicon-log-in:before { - content: "\e161"; -} - -.glyphicon-flash:before { - content: "\e162"; -} - -.glyphicon-log-out:before { - content: "\e163"; -} - -.glyphicon-new-window:before { - content: "\e164"; -} - -.glyphicon-record:before { - content: "\e165"; -} - -.glyphicon-save:before { - content: "\e166"; -} - -.glyphicon-open:before { - content: "\e167"; -} - -.glyphicon-saved:before { - content: "\e168"; -} - -.glyphicon-import:before { - content: "\e169"; -} - -.glyphicon-export:before { - content: "\e170"; -} - -.glyphicon-send:before { - content: "\e171"; -} - -.glyphicon-floppy-disk:before { - content: "\e172"; -} - -.glyphicon-floppy-saved:before { - content: "\e173"; -} - -.glyphicon-floppy-remove:before { - content: "\e174"; -} - -.glyphicon-floppy-save:before { - content: "\e175"; -} - -.glyphicon-floppy-open:before { - content: "\e176"; -} - -.glyphicon-credit-card:before { - content: "\e177"; -} - -.glyphicon-transfer:before { - content: "\e178"; -} - -.glyphicon-cutlery:before { - content: "\e179"; -} - -.glyphicon-header:before { - content: "\e180"; -} - -.glyphicon-compressed:before { - content: "\e181"; -} - -.glyphicon-earphone:before { - content: "\e182"; -} - -.glyphicon-phone-alt:before { - content: "\e183"; -} - -.glyphicon-tower:before { - content: "\e184"; -} - -.glyphicon-stats:before { - content: "\e185"; -} - -.glyphicon-sd-video:before { - content: "\e186"; -} - -.glyphicon-hd-video:before { - content: "\e187"; -} - -.glyphicon-subtitles:before { - content: "\e188"; -} - -.glyphicon-sound-stereo:before { - content: "\e189"; -} - -.glyphicon-sound-dolby:before { - content: "\e190"; -} - -.glyphicon-sound-5-1:before { - content: "\e191"; -} - -.glyphicon-sound-6-1:before { - content: "\e192"; -} - -.glyphicon-sound-7-1:before { - content: "\e193"; -} - -.glyphicon-copyright-mark:before { - content: "\e194"; -} - -.glyphicon-registration-mark:before { - content: "\e195"; -} - -.glyphicon-cloud-download:before { - content: "\e197"; -} - -.glyphicon-cloud-upload:before { - content: "\e198"; -} - -.glyphicon-tree-conifer:before { - content: "\e199"; -} - -.glyphicon-tree-deciduous:before { - content: "\e200"; -} - -.caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: 4px solid; - border-right: 4px solid transparent; - border-left: 4px solid transparent; -} - -.dropdown { - position: relative; -} - -.dropdown-toggle:focus { - outline: 0; -} - -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - font-size: 14px; - list-style: none; - background-color: #ffffff; - border: 1px solid #cccccc; - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); - box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); - background-clip: padding-box; -} - -.dropdown-menu.pull-right { - right: 0; - left: auto; -} - -.dropdown-menu .divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} - -.dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 1.428571429; - color: #333333; - white-space: nowrap; -} - -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus { - color: #262626; - text-decoration: none; - background-color: #f5f5f5; -} - -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - color: #ffffff; - text-decoration: none; - background-color: #428bca; - outline: 0; -} - -.dropdown-menu > .disabled > a, -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - color: #999999; -} - -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - text-decoration: none; - cursor: not-allowed; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); -} - -.open > .dropdown-menu { - display: block; -} - -.open > a { - outline: 0; -} - -.dropdown-header { - display: block; - padding: 3px 20px; - font-size: 12px; - line-height: 1.428571429; - color: #999999; -} - -.dropdown-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 990; -} - -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} - -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - border-top: 0; - border-bottom: 4px solid; - content: ""; -} - -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 1px; -} - -@media (min-width: 768px) { - .navbar-right .dropdown-menu { - right: 0; - left: auto; - } -} - -.btn-group, -.btn-group-vertical { - position: relative; - display: inline-block; - vertical-align: middle; -} - -.btn-group > .btn, -.btn-group-vertical > .btn { - position: relative; - float: left; -} - -.btn-group > .btn:hover, -.btn-group-vertical > .btn:hover, -.btn-group > .btn:focus, -.btn-group-vertical > .btn:focus, -.btn-group > .btn:active, -.btn-group-vertical > .btn:active, -.btn-group > .btn.active, -.btn-group-vertical > .btn.active { - z-index: 2; -} - -.btn-group > .btn:focus, -.btn-group-vertical > .btn:focus { - outline: none; -} - -.btn-group .btn + .btn, -.btn-group .btn + .btn-group, -.btn-group .btn-group + .btn, -.btn-group .btn-group + .btn-group { - margin-left: -1px; -} - -.btn-toolbar:before, -.btn-toolbar:after { - display: table; - content: " "; -} - -.btn-toolbar:after { - clear: both; -} - -.btn-toolbar:before, -.btn-toolbar:after { - display: table; - content: " "; -} - -.btn-toolbar:after { - clear: both; -} - -.btn-toolbar .btn-group { - float: left; -} - -.btn-toolbar > .btn + .btn, -.btn-toolbar > .btn-group + .btn, -.btn-toolbar > .btn + .btn-group, -.btn-toolbar > .btn-group + .btn-group { - margin-left: 5px; -} - -.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { - border-radius: 0; -} - -.btn-group > .btn:first-child { - margin-left: 0; -} - -.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -.btn-group > .btn:last-child:not(:first-child), -.btn-group > .dropdown-toggle:not(:first-child) { - border-bottom-left-radius: 0; - border-top-left-radius: 0; -} - -.btn-group > .btn-group { - float: left; -} - -.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} - -.btn-group > .btn-group:first-child > .btn:last-child, -.btn-group > .btn-group:first-child > .dropdown-toggle { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -.btn-group > .btn-group:last-child > .btn:first-child { - border-bottom-left-radius: 0; - border-top-left-radius: 0; -} - -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} - -.btn-group-xs > .btn { - padding: 1px 5px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} - -.btn-group-sm > .btn { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} - -.btn-group-lg > .btn { - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; -} - -.btn-group > .btn + .dropdown-toggle { - padding-right: 8px; - padding-left: 8px; -} - -.btn-group > .btn-lg + .dropdown-toggle { - padding-right: 12px; - padding-left: 12px; -} - -.btn-group.open .dropdown-toggle { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); -} - -.btn-group.open .dropdown-toggle.btn-link { - -webkit-box-shadow: none; - box-shadow: none; -} - -.btn .caret { - margin-left: 0; -} - -.btn-lg .caret { - border-width: 5px 5px 0; - border-bottom-width: 0; -} - -.dropup .btn-lg .caret { - border-width: 0 5px 5px; -} - -.btn-group-vertical > .btn, -.btn-group-vertical > .btn-group, -.btn-group-vertical > .btn-group > .btn { - display: block; - float: none; - width: 100%; - max-width: 100%; -} - -.btn-group-vertical > .btn-group:before, -.btn-group-vertical > .btn-group:after { - display: table; - content: " "; -} - -.btn-group-vertical > .btn-group:after { - clear: both; -} - -.btn-group-vertical > .btn-group:before, -.btn-group-vertical > .btn-group:after { - display: table; - content: " "; -} - -.btn-group-vertical > .btn-group:after { - clear: both; -} - -.btn-group-vertical > .btn-group > .btn { - float: none; -} - -.btn-group-vertical > .btn + .btn, -.btn-group-vertical > .btn + .btn-group, -.btn-group-vertical > .btn-group + .btn, -.btn-group-vertical > .btn-group + .btn-group { - margin-top: -1px; - margin-left: 0; -} - -.btn-group-vertical > .btn:not(:first-child):not(:last-child) { - border-radius: 0; -} - -.btn-group-vertical > .btn:first-child:not(:last-child) { - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} - -.btn-group-vertical > .btn:last-child:not(:first-child) { - border-top-right-radius: 0; - border-bottom-left-radius: 4px; - border-top-left-radius: 0; -} - -.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} - -.btn-group-vertical > .btn-group:first-child > .btn:last-child, -.btn-group-vertical > .btn-group:first-child > .dropdown-toggle { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} - -.btn-group-vertical > .btn-group:last-child > .btn:first-child { - border-top-right-radius: 0; - border-top-left-radius: 0; -} - -.btn-group-justified { - display: table; - width: 100%; - border-collapse: separate; - table-layout: fixed; -} - -.btn-group-justified > .btn, -.btn-group-justified > .btn-group { - display: table-cell; - float: none; - width: 1%; -} - -.btn-group-justified > .btn-group .btn { - width: 100%; -} - -[data-toggle="buttons"] > .btn > input[type="radio"], -[data-toggle="buttons"] > .btn > input[type="checkbox"] { - display: none; -} - -.input-group { - position: relative; - display: table; - border-collapse: separate; -} - -.input-group[class*="col-"] { - float: none; - padding-right: 0; - padding-left: 0; -} - -.input-group .form-control { - width: 100%; - margin-bottom: 0; -} - -.input-group-lg > .form-control, -.input-group-lg > .input-group-addon, -.input-group-lg > .input-group-btn > .btn { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; -} - -select.input-group-lg > .form-control, -select.input-group-lg > .input-group-addon, -select.input-group-lg > .input-group-btn > .btn { - height: 46px; - line-height: 46px; -} - -textarea.input-group-lg > .form-control, -textarea.input-group-lg > .input-group-addon, -textarea.input-group-lg > .input-group-btn > .btn { - height: auto; -} - -.input-group-sm > .form-control, -.input-group-sm > .input-group-addon, -.input-group-sm > .input-group-btn > .btn { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} - -select.input-group-sm > .form-control, -select.input-group-sm > .input-group-addon, -select.input-group-sm > .input-group-btn > .btn { - height: 30px; - line-height: 30px; -} - -textarea.input-group-sm > .form-control, -textarea.input-group-sm > .input-group-addon, -textarea.input-group-sm > .input-group-btn > .btn { - height: auto; -} - -.input-group-addon, -.input-group-btn, -.input-group .form-control { - display: table-cell; -} - -.input-group-addon:not(:first-child):not(:last-child), -.input-group-btn:not(:first-child):not(:last-child), -.input-group .form-control:not(:first-child):not(:last-child) { - border-radius: 0; -} - -.input-group-addon, -.input-group-btn { - width: 1%; - white-space: nowrap; - vertical-align: middle; -} - -.input-group-addon { - padding: 6px 12px; - font-size: 14px; - font-weight: normal; - line-height: 1; - color: #555555; - text-align: center; - background-color: #eeeeee; - border: 1px solid #cccccc; - border-radius: 4px; -} - -.input-group-addon.input-sm { - padding: 5px 10px; - font-size: 12px; - border-radius: 3px; -} - -.input-group-addon.input-lg { - padding: 10px 16px; - font-size: 18px; - border-radius: 6px; -} - -.input-group-addon input[type="radio"], -.input-group-addon input[type="checkbox"] { - margin-top: 0; -} - -.input-group .form-control:first-child, -.input-group-addon:first-child, -.input-group-btn:first-child > .btn, -.input-group-btn:first-child > .dropdown-toggle, -.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -.input-group-addon:first-child { - border-right: 0; -} - -.input-group .form-control:last-child, -.input-group-addon:last-child, -.input-group-btn:last-child > .btn, -.input-group-btn:last-child > .dropdown-toggle, -.input-group-btn:first-child > .btn:not(:first-child) { - border-bottom-left-radius: 0; - border-top-left-radius: 0; -} - -.input-group-addon:last-child { - border-left: 0; -} - -.input-group-btn { - position: relative; - white-space: nowrap; -} - -.input-group-btn:first-child > .btn { - margin-right: -1px; -} - -.input-group-btn:last-child > .btn { - margin-left: -1px; -} - -.input-group-btn > .btn { - position: relative; -} - -.input-group-btn > .btn + .btn { - margin-left: -4px; -} - -.input-group-btn > .btn:hover, -.input-group-btn > .btn:active { - z-index: 2; -} - -.nav { - padding-left: 0; - margin-bottom: 0; - list-style: none; -} - -.nav:before, -.nav:after { - display: table; - content: " "; -} - -.nav:after { - clear: both; -} - -.nav:before, -.nav:after { - display: table; - content: " "; -} - -.nav:after { - clear: both; -} - -.nav > li { - position: relative; - display: block; -} - -.nav > li > a { - position: relative; - display: block; - padding: 10px 15px; -} - -.nav > li > a:hover, -.nav > li > a:focus { - text-decoration: none; - background-color: #eeeeee; -} - -.nav > li.disabled > a { - color: #999999; -} - -.nav > li.disabled > a:hover, -.nav > li.disabled > a:focus { - color: #999999; - text-decoration: none; - cursor: not-allowed; - background-color: transparent; -} - -.nav .open > a, -.nav .open > a:hover, -.nav .open > a:focus { - background-color: #eeeeee; - border-color: #428bca; -} - -.nav .nav-divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} - -.nav > li > a > img { - max-width: none; -} - -.nav-tabs { - border-bottom: 1px solid #dddddd; -} - -.nav-tabs > li { - float: left; - margin-bottom: -1px; -} - -.nav-tabs > li > a { - margin-right: 2px; - line-height: 1.428571429; - border: 1px solid transparent; - border-radius: 4px 4px 0 0; -} - -.nav-tabs > li > a:hover { - border-color: #eeeeee #eeeeee #dddddd; -} - -.nav-tabs > li.active > a, -.nav-tabs > li.active > a:hover, -.nav-tabs > li.active > a:focus { - color: #555555; - cursor: default; - background-color: #ffffff; - border: 1px solid #dddddd; - border-bottom-color: transparent; -} - -.nav-tabs.nav-justified { - width: 100%; - border-bottom: 0; -} - -.nav-tabs.nav-justified > li { - float: none; -} - -.nav-tabs.nav-justified > li > a { - margin-bottom: 5px; - text-align: center; -} - -.nav-tabs.nav-justified > .dropdown .dropdown-menu { - top: auto; - left: auto; -} - -@media (min-width: 768px) { - .nav-tabs.nav-justified > li { - display: table-cell; - width: 1%; - } - .nav-tabs.nav-justified > li > a { - margin-bottom: 0; - } -} - -.nav-tabs.nav-justified > li > a { - margin-right: 0; - border-radius: 4px; -} - -.nav-tabs.nav-justified > .active > a, -.nav-tabs.nav-justified > .active > a:hover, -.nav-tabs.nav-justified > .active > a:focus { - border: 1px solid #dddddd; -} - -@media (min-width: 768px) { - .nav-tabs.nav-justified > li > a { - border-bottom: 1px solid #dddddd; - border-radius: 4px 4px 0 0; - } - .nav-tabs.nav-justified > .active > a, - .nav-tabs.nav-justified > .active > a:hover, - .nav-tabs.nav-justified > .active > a:focus { - border-bottom-color: #ffffff; - } -} - -.nav-pills > li { - float: left; -} - -.nav-pills > li > a { - border-radius: 4px; -} - -.nav-pills > li + li { - margin-left: 2px; -} - -.nav-pills > li.active > a, -.nav-pills > li.active > a:hover, -.nav-pills > li.active > a:focus { - color: #ffffff; - background-color: #428bca; -} - -.nav-stacked > li { - float: none; -} - -.nav-stacked > li + li { - margin-top: 2px; - margin-left: 0; -} - -.nav-justified { - width: 100%; -} - -.nav-justified > li { - float: none; -} - -.nav-justified > li > a { - margin-bottom: 5px; - text-align: center; -} - -.nav-justified > .dropdown .dropdown-menu { - top: auto; - left: auto; -} - -@media (min-width: 768px) { - .nav-justified > li { - display: table-cell; - width: 1%; - } - .nav-justified > li > a { - margin-bottom: 0; - } -} - -.nav-tabs-justified { - border-bottom: 0; -} - -.nav-tabs-justified > li > a { - margin-right: 0; - border-radius: 4px; -} - -.nav-tabs-justified > .active > a, -.nav-tabs-justified > .active > a:hover, -.nav-tabs-justified > .active > a:focus { - border: 1px solid #dddddd; -} - -@media (min-width: 768px) { - .nav-tabs-justified > li > a { - border-bottom: 1px solid #dddddd; - border-radius: 4px 4px 0 0; - } - .nav-tabs-justified > .active > a, - .nav-tabs-justified > .active > a:hover, - .nav-tabs-justified > .active > a:focus { - border-bottom-color: #ffffff; - } -} - -.tab-content > .tab-pane { - display: none; -} - -.tab-content > .active { - display: block; -} - -.nav-tabs .dropdown-menu { - margin-top: -1px; - border-top-right-radius: 0; - border-top-left-radius: 0; -} - -.navbar { - position: relative; - min-height: 50px; - margin-bottom: 20px; - border: 1px solid transparent; -} - -.navbar:before, -.navbar:after { - display: table; - content: " "; -} - -.navbar:after { - clear: both; -} - -.navbar:before, -.navbar:after { - display: table; - content: " "; -} - -.navbar:after { - clear: both; -} - -@media (min-width: 768px) { - .navbar { - border-radius: 4px; - } -} - -.navbar-header:before, -.navbar-header:after { - display: table; - content: " "; -} - -.navbar-header:after { - clear: both; -} - -.navbar-header:before, -.navbar-header:after { - display: table; - content: " "; -} - -.navbar-header:after { - clear: both; -} - -@media (min-width: 768px) { - .navbar-header { - float: left; - } -} - -.navbar-collapse { - max-height: 340px; - padding-right: 15px; - padding-left: 15px; - overflow-x: visible; - border-top: 1px solid transparent; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); - -webkit-overflow-scrolling: touch; -} - -.navbar-collapse:before, -.navbar-collapse:after { - display: table; - content: " "; -} - -.navbar-collapse:after { - clear: both; -} - -.navbar-collapse:before, -.navbar-collapse:after { - display: table; - content: " "; -} - -.navbar-collapse:after { - clear: both; -} - -.navbar-collapse.in { - overflow-y: auto; -} - -@media (min-width: 768px) { - .navbar-collapse { - width: auto; - border-top: 0; - box-shadow: none; - } - .navbar-collapse.collapse { - display: block !important; - height: auto !important; - padding-bottom: 0; - overflow: visible !important; - } - .navbar-collapse.in { - overflow-y: visible; - } - .navbar-fixed-top .navbar-collapse, - .navbar-static-top .navbar-collapse, - .navbar-fixed-bottom .navbar-collapse { - padding-right: 0; - padding-left: 0; - } -} - -.container > .navbar-header, -.container > .navbar-collapse { - margin-right: -15px; - margin-left: -15px; -} - -@media (min-width: 768px) { - .container > .navbar-header, - .container > .navbar-collapse { - margin-right: 0; - margin-left: 0; - } -} - -.navbar-static-top { - z-index: 1000; - border-width: 0 0 1px; -} - -@media (min-width: 768px) { - .navbar-static-top { - border-radius: 0; - } -} - -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: 1030; -} - -@media (min-width: 768px) { - .navbar-fixed-top, - .navbar-fixed-bottom { - border-radius: 0; - } -} - -.navbar-fixed-top { - top: 0; - border-width: 0 0 1px; -} - -.navbar-fixed-bottom { - bottom: 0; - margin-bottom: 0; - border-width: 1px 0 0; -} - -.navbar-brand { - float: left; - padding: 15px 15px; - font-size: 18px; - line-height: 20px; -} - -.navbar-brand:hover, -.navbar-brand:focus { - text-decoration: none; -} - -@media (min-width: 768px) { - .navbar > .container .navbar-brand { - margin-left: -15px; - } -} - -.navbar-toggle { - position: relative; - float: right; - padding: 9px 10px; - margin-top: 8px; - margin-right: 15px; - margin-bottom: 8px; - background-color: transparent; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; -} - -.navbar-toggle .icon-bar { - display: block; - width: 22px; - height: 2px; - border-radius: 1px; -} - -.navbar-toggle .icon-bar + .icon-bar { - margin-top: 4px; -} - -@media (min-width: 768px) { - .navbar-toggle { - display: none; - } -} - -.navbar-nav { - margin: 7.5px -15px; -} - -.navbar-nav > li > a { - padding-top: 10px; - padding-bottom: 10px; - line-height: 20px; -} - -@media (max-width: 767px) { - .navbar-nav .open .dropdown-menu { - position: static; - float: none; - width: auto; - margin-top: 0; - background-color: transparent; - border: 0; - box-shadow: none; - } - .navbar-nav .open .dropdown-menu > li > a, - .navbar-nav .open .dropdown-menu .dropdown-header { - padding: 5px 15px 5px 25px; - } - .navbar-nav .open .dropdown-menu > li > a { - line-height: 20px; - } - .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-nav .open .dropdown-menu > li > a:focus { - background-image: none; - } -} - -@media (min-width: 768px) { - .navbar-nav { - float: left; - margin: 0; - } - .navbar-nav > li { - float: left; - } - .navbar-nav > li > a { - padding-top: 15px; - padding-bottom: 15px; - } - .navbar-nav.navbar-right:last-child { - margin-right: -15px; - } -} - -@media (min-width: 768px) { - .navbar-left { - float: left !important; - } - .navbar-right { - float: right !important; - } -} - -.navbar-form { - padding: 10px 15px; - margin-top: 8px; - margin-right: -15px; - margin-bottom: 8px; - margin-left: -15px; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); -} - -@media (min-width: 768px) { - .navbar-form .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .form-control { - display: inline-block; - } - .navbar-form select.form-control { - width: auto; - } - .navbar-form .radio, - .navbar-form .checkbox { - display: inline-block; - padding-left: 0; - margin-top: 0; - margin-bottom: 0; - } - .navbar-form .radio input[type="radio"], - .navbar-form .checkbox input[type="checkbox"] { - float: none; - margin-left: 0; - } -} - -@media (max-width: 767px) { - .navbar-form .form-group { - margin-bottom: 5px; - } -} - -@media (min-width: 768px) { - .navbar-form { - width: auto; - padding-top: 0; - padding-bottom: 0; - margin-right: 0; - margin-left: 0; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - } - .navbar-form.navbar-right:last-child { - margin-right: -15px; - } -} - -.navbar-nav > li > .dropdown-menu { - margin-top: 0; - border-top-right-radius: 0; - border-top-left-radius: 0; -} - -.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} - -.navbar-nav.pull-right > li > .dropdown-menu, -.navbar-nav > li > .dropdown-menu.pull-right { - right: 0; - left: auto; -} - -.navbar-btn { - margin-top: 8px; - margin-bottom: 8px; -} - -.navbar-btn.btn-sm { - margin-top: 10px; - margin-bottom: 10px; -} - -.navbar-btn.btn-xs { - margin-top: 14px; - margin-bottom: 14px; -} - -.navbar-text { - margin-top: 15px; - margin-bottom: 15px; -} - -@media (min-width: 768px) { - .navbar-text { - float: left; - margin-right: 15px; - margin-left: 15px; - } - .navbar-text.navbar-right:last-child { - margin-right: 0; - } -} - -.navbar-default { - background-color: #f8f8f8; - border-color: #e7e7e7; -} - -.navbar-default .navbar-brand { - color: #777777; -} - -.navbar-default .navbar-brand:hover, -.navbar-default .navbar-brand:focus { - color: #5e5e5e; - background-color: transparent; -} - -.navbar-default .navbar-text { - color: #777777; -} - -.navbar-default .navbar-nav > li > a { - color: #777777; -} - -.navbar-default .navbar-nav > li > a:hover, -.navbar-default .navbar-nav > li > a:focus { - color: #333333; - background-color: transparent; -} - -.navbar-default .navbar-nav > .active > a, -.navbar-default .navbar-nav > .active > a:hover, -.navbar-default .navbar-nav > .active > a:focus { - color: #555555; - background-color: #e7e7e7; -} - -.navbar-default .navbar-nav > .disabled > a, -.navbar-default .navbar-nav > .disabled > a:hover, -.navbar-default .navbar-nav > .disabled > a:focus { - color: #cccccc; - background-color: transparent; -} - -.navbar-default .navbar-toggle { - border-color: #dddddd; -} - -.navbar-default .navbar-toggle:hover, -.navbar-default .navbar-toggle:focus { - background-color: #dddddd; -} - -.navbar-default .navbar-toggle .icon-bar { - background-color: #cccccc; -} - -.navbar-default .navbar-collapse, -.navbar-default .navbar-form { - border-color: #e7e7e7; -} - -.navbar-default .navbar-nav > .open > a, -.navbar-default .navbar-nav > .open > a:hover, -.navbar-default .navbar-nav > .open > a:focus { - color: #555555; - background-color: #e7e7e7; -} - -@media (max-width: 767px) { - .navbar-default .navbar-nav .open .dropdown-menu > li > a { - color: #777777; - } - .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { - color: #333333; - background-color: transparent; - } - .navbar-default .navbar-nav .open .dropdown-menu > .active > a, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #555555; - background-color: #e7e7e7; - } - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #cccccc; - background-color: transparent; - } -} - -.navbar-default .navbar-link { - color: #777777; -} - -.navbar-default .navbar-link:hover { - color: #333333; -} - -.navbar-inverse { - background-color: #222222; - border-color: #080808; -} - -.navbar-inverse .navbar-brand { - color: #999999; -} - -.navbar-inverse .navbar-brand:hover, -.navbar-inverse .navbar-brand:focus { - color: #ffffff; - background-color: transparent; -} - -.navbar-inverse .navbar-text { - color: #999999; -} - -.navbar-inverse .navbar-nav > li > a { - color: #999999; -} - -.navbar-inverse .navbar-nav > li > a:hover, -.navbar-inverse .navbar-nav > li > a:focus { - color: #ffffff; - background-color: transparent; -} - -.navbar-inverse .navbar-nav > .active > a, -.navbar-inverse .navbar-nav > .active > a:hover, -.navbar-inverse .navbar-nav > .active > a:focus { - color: #ffffff; - background-color: #080808; -} - -.navbar-inverse .navbar-nav > .disabled > a, -.navbar-inverse .navbar-nav > .disabled > a:hover, -.navbar-inverse .navbar-nav > .disabled > a:focus { - color: #444444; - background-color: transparent; -} - -.navbar-inverse .navbar-toggle { - border-color: #333333; -} - -.navbar-inverse .navbar-toggle:hover, -.navbar-inverse .navbar-toggle:focus { - background-color: #333333; -} - -.navbar-inverse .navbar-toggle .icon-bar { - background-color: #ffffff; -} - -.navbar-inverse .navbar-collapse, -.navbar-inverse .navbar-form { - border-color: #101010; -} - -.navbar-inverse .navbar-nav > .open > a, -.navbar-inverse .navbar-nav > .open > a:hover, -.navbar-inverse .navbar-nav > .open > a:focus { - color: #ffffff; - background-color: #080808; -} - -@media (max-width: 767px) { - .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { - border-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu .divider { - background-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { - color: #999999; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { - color: #ffffff; - background-color: transparent; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #ffffff; - background-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #444444; - background-color: transparent; - } -} - -.navbar-inverse .navbar-link { - color: #999999; -} - -.navbar-inverse .navbar-link:hover { - color: #ffffff; -} - -.breadcrumb { - padding: 8px 15px; - margin-bottom: 20px; - list-style: none; - background-color: #f5f5f5; - border-radius: 4px; -} - -.breadcrumb > li { - display: inline-block; -} - -.breadcrumb > li + li:before { - padding: 0 5px; - color: #cccccc; - content: "/\00a0"; -} - -.breadcrumb > .active { - color: #999999; -} - -.pagination { - display: inline-block; - padding-left: 0; - margin: 20px 0; - border-radius: 4px; -} - -.pagination > li { - display: inline; -} - -.pagination > li > a, -.pagination > li > span { - position: relative; - float: left; - padding: 6px 12px; - margin-left: -1px; - line-height: 1.428571429; - text-decoration: none; - background-color: #ffffff; - border: 1px solid #dddddd; -} - -.pagination > li:first-child > a, -.pagination > li:first-child > span { - margin-left: 0; - border-bottom-left-radius: 4px; - border-top-left-radius: 4px; -} - -.pagination > li:last-child > a, -.pagination > li:last-child > span { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; -} - -.pagination > li > a:hover, -.pagination > li > span:hover, -.pagination > li > a:focus, -.pagination > li > span:focus { - background-color: #eeeeee; -} - -.pagination > .active > a, -.pagination > .active > span, -.pagination > .active > a:hover, -.pagination > .active > span:hover, -.pagination > .active > a:focus, -.pagination > .active > span:focus { - z-index: 2; - color: #ffffff; - cursor: default; - background-color: #428bca; - border-color: #428bca; -} - -.pagination > .disabled > span, -.pagination > .disabled > span:hover, -.pagination > .disabled > span:focus, -.pagination > .disabled > a, -.pagination > .disabled > a:hover, -.pagination > .disabled > a:focus { - color: #999999; - cursor: not-allowed; - background-color: #ffffff; - border-color: #dddddd; -} - -.pagination-lg > li > a, -.pagination-lg > li > span { - padding: 10px 16px; - font-size: 18px; -} - -.pagination-lg > li:first-child > a, -.pagination-lg > li:first-child > span { - border-bottom-left-radius: 6px; - border-top-left-radius: 6px; -} - -.pagination-lg > li:last-child > a, -.pagination-lg > li:last-child > span { - border-top-right-radius: 6px; - border-bottom-right-radius: 6px; -} - -.pagination-sm > li > a, -.pagination-sm > li > span { - padding: 5px 10px; - font-size: 12px; -} - -.pagination-sm > li:first-child > a, -.pagination-sm > li:first-child > span { - border-bottom-left-radius: 3px; - border-top-left-radius: 3px; -} - -.pagination-sm > li:last-child > a, -.pagination-sm > li:last-child > span { - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; -} - -.pager { - padding-left: 0; - margin: 20px 0; - text-align: center; - list-style: none; -} - -.pager:before, -.pager:after { - display: table; - content: " "; -} - -.pager:after { - clear: both; -} - -.pager:before, -.pager:after { - display: table; - content: " "; -} - -.pager:after { - clear: both; -} - -.pager li { - display: inline; -} - -.pager li > a, -.pager li > span { - display: inline-block; - padding: 5px 14px; - background-color: #ffffff; - border: 1px solid #dddddd; - border-radius: 15px; -} - -.pager li > a:hover, -.pager li > a:focus { - text-decoration: none; - background-color: #eeeeee; -} - -.pager .next > a, -.pager .next > span { - float: right; -} - -.pager .previous > a, -.pager .previous > span { - float: left; -} - -.pager .disabled > a, -.pager .disabled > a:hover, -.pager .disabled > a:focus, -.pager .disabled > span { - color: #999999; - cursor: not-allowed; - background-color: #ffffff; -} - -.label { - display: inline; - padding: .2em .6em .3em; - font-size: 75%; - font-weight: bold; - line-height: 1; - color: #ffffff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em; -} - -.label[href]:hover, -.label[href]:focus { - color: #ffffff; - text-decoration: none; - cursor: pointer; -} - -.label:empty { - display: none; -} - -.btn .label { - position: relative; - top: -1px; -} - -.label-default { - background-color: #999999; -} - -.label-default[href]:hover, -.label-default[href]:focus { - background-color: #808080; -} - -.label-primary { - background-color: #428bca; -} - -.label-primary[href]:hover, -.label-primary[href]:focus { - background-color: #3071a9; -} - -.label-success { - background-color: #5cb85c; -} - -.label-success[href]:hover, -.label-success[href]:focus { - background-color: #449d44; -} - -.label-info { - background-color: #5bc0de; -} - -.label-info[href]:hover, -.label-info[href]:focus { - background-color: #31b0d5; -} - -.label-warning { - background-color: #f0ad4e; -} - -.label-warning[href]:hover, -.label-warning[href]:focus { - background-color: #ec971f; -} - -.label-danger { - background-color: #d9534f; -} - -.label-danger[href]:hover, -.label-danger[href]:focus { - background-color: #c9302c; -} - -.badge { - display: inline-block; - min-width: 10px; - padding: 3px 7px; - font-size: 12px; - font-weight: bold; - line-height: 1; - color: #ffffff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - background-color: #999999; - border-radius: 10px; -} - -.badge:empty { - display: none; -} - -.btn .badge { - position: relative; - top: -1px; -} - -a.badge:hover, -a.badge:focus { - color: #ffffff; - text-decoration: none; - cursor: pointer; -} - -a.list-group-item.active > .badge, -.nav-pills > .active > a > .badge { - color: #428bca; - background-color: #ffffff; -} - -.nav-pills > li > a > .badge { - margin-left: 3px; -} - -.jumbotron { - padding: 30px; - margin-bottom: 30px; - font-size: 21px; - font-weight: 200; - line-height: 2.1428571435; - color: inherit; - background-color: #eeeeee; -} - -.jumbotron h1, -.jumbotron .h1 { - line-height: 1; - color: inherit; -} - -.jumbotron p { - line-height: 1.4; -} - -.container .jumbotron { - border-radius: 6px; -} - -.jumbotron .container { - max-width: 100%; -} - -@media screen and (min-width: 768px) { - .jumbotron { - padding-top: 48px; - padding-bottom: 48px; - } - .container .jumbotron { - padding-right: 60px; - padding-left: 60px; - } - .jumbotron h1, - .jumbotron .h1 { - font-size: 63px; - } -} - -.thumbnail { - display: block; - padding: 4px; - margin-bottom: 20px; - line-height: 1.428571429; - background-color: #ffffff; - border: 1px solid #dddddd; - border-radius: 4px; - -webkit-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; -} - -.thumbnail > img, -.thumbnail a > img { - display: block; - height: auto; - max-width: 100%; - margin-right: auto; - margin-left: auto; -} - -a.thumbnail:hover, -a.thumbnail:focus, -a.thumbnail.active { - border-color: #428bca; -} - -.thumbnail .caption { - padding: 9px; - color: #333333; -} - -.alert { - padding: 15px; - margin-bottom: 20px; - border: 1px solid transparent; - border-radius: 4px; -} - -.alert h4 { - margin-top: 0; - color: inherit; -} - -.alert .alert-link { - font-weight: bold; -} - -.alert > p, -.alert > ul { - margin-bottom: 0; -} - -.alert > p + p { - margin-top: 5px; -} - -.alert-dismissable { - padding-right: 35px; -} - -.alert-dismissable .close { - position: relative; - top: -2px; - right: -21px; - color: inherit; -} - -.alert-success { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; -} - -.alert-success hr { - border-top-color: #c9e2b3; -} - -.alert-success .alert-link { - color: #2b542c; -} - -.alert-info { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; -} - -.alert-info hr { - border-top-color: #a6e1ec; -} - -.alert-info .alert-link { - color: #245269; -} - -.alert-warning { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; -} - -.alert-warning hr { - border-top-color: #f7e1b5; -} - -.alert-warning .alert-link { - color: #66512c; -} - -.alert-danger { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; -} - -.alert-danger hr { - border-top-color: #e4b9c0; -} - -.alert-danger .alert-link { - color: #843534; -} - -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -@keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} - -.progress { - height: 20px; - margin-bottom: 20px; - overflow: hidden; - background-color: #f5f5f5; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -} - -.progress-bar { - float: left; - width: 0; - height: 100%; - font-size: 12px; - line-height: 20px; - color: #ffffff; - text-align: center; - background-color: #428bca; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); - -webkit-transition: width 0.6s ease; - transition: width 0.6s ease; -} - -.progress-striped .progress-bar { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-size: 40px 40px; -} - -.progress.active .progress-bar { - -webkit-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} - -.progress-bar-success { - background-color: #5cb85c; -} - -.progress-striped .progress-bar-success { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-bar-info { - background-color: #5bc0de; -} - -.progress-striped .progress-bar-info { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-bar-warning { - background-color: #f0ad4e; -} - -.progress-striped .progress-bar-warning { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.progress-bar-danger { - background-color: #d9534f; -} - -.progress-striped .progress-bar-danger { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); -} - -.media, -.media-body { - overflow: hidden; - zoom: 1; -} - -.media, -.media .media { - margin-top: 15px; -} - -.media:first-child { - margin-top: 0; -} - -.media-object { - display: block; -} - -.media-heading { - margin: 0 0 5px; -} - -.media > .pull-left { - margin-right: 10px; -} - -.media > .pull-right { - margin-left: 10px; -} - -.media-list { - padding-left: 0; - list-style: none; -} - -.list-group { - padding-left: 0; - margin-bottom: 20px; -} - -.list-group-item { - position: relative; - display: block; - padding: 10px 15px; - margin-bottom: -1px; - background-color: #ffffff; - border: 1px solid #dddddd; -} - -.list-group-item:first-child { - border-top-right-radius: 4px; - border-top-left-radius: 4px; -} - -.list-group-item:last-child { - margin-bottom: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; -} - -.list-group-item > .badge { - float: right; -} - -.list-group-item > .badge + .badge { - margin-right: 5px; -} - -a.list-group-item { - color: #555555; -} - -a.list-group-item .list-group-item-heading { - color: #333333; -} - -a.list-group-item:hover, -a.list-group-item:focus { - text-decoration: none; - background-color: #f5f5f5; -} - -a.list-group-item.active, -a.list-group-item.active:hover, -a.list-group-item.active:focus { - z-index: 2; - color: #ffffff; - background-color: #428bca; - border-color: #428bca; -} - -a.list-group-item.active .list-group-item-heading, -a.list-group-item.active:hover .list-group-item-heading, -a.list-group-item.active:focus .list-group-item-heading { - color: inherit; -} - -a.list-group-item.active .list-group-item-text, -a.list-group-item.active:hover .list-group-item-text, -a.list-group-item.active:focus .list-group-item-text { - color: #e1edf7; -} - -.list-group-item-heading { - margin-top: 0; - margin-bottom: 5px; -} - -.list-group-item-text { - margin-bottom: 0; - line-height: 1.3; -} - -.panel { - margin-bottom: 20px; - background-color: #ffffff; - border: 1px solid transparent; - border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); -} - -.panel-body { - padding: 15px; -} - -.panel-body:before, -.panel-body:after { - display: table; - content: " "; -} - -.panel-body:after { - clear: both; -} - -.panel-body:before, -.panel-body:after { - display: table; - content: " "; -} - -.panel-body:after { - clear: both; -} - -.panel > .list-group { - margin-bottom: 0; -} - -.panel > .list-group .list-group-item { - border-width: 1px 0; -} - -.panel > .list-group .list-group-item:first-child { - border-top-right-radius: 0; - border-top-left-radius: 0; -} - -.panel > .list-group .list-group-item:last-child { - border-bottom: 0; -} - -.panel-heading + .list-group .list-group-item:first-child { - border-top-width: 0; -} - -.panel > .table, -.panel > .table-responsive > .table { - margin-bottom: 0; -} - -.panel > .panel-body + .table, -.panel > .panel-body + .table-responsive { - border-top: 1px solid #dddddd; -} - -.panel > .table > tbody:first-child th, -.panel > .table > tbody:first-child td { - border-top: 0; -} - -.panel > .table-bordered, -.panel > .table-responsive > .table-bordered { - border: 0; -} - -.panel > .table-bordered > thead > tr > th:first-child, -.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, -.panel > .table-bordered > tbody > tr > th:first-child, -.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, -.panel > .table-bordered > tfoot > tr > th:first-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, -.panel > .table-bordered > thead > tr > td:first-child, -.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, -.panel > .table-bordered > tbody > tr > td:first-child, -.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, -.panel > .table-bordered > tfoot > tr > td:first-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; -} - -.panel > .table-bordered > thead > tr > th:last-child, -.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, -.panel > .table-bordered > tbody > tr > th:last-child, -.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, -.panel > .table-bordered > tfoot > tr > th:last-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, -.panel > .table-bordered > thead > tr > td:last-child, -.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, -.panel > .table-bordered > tbody > tr > td:last-child, -.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, -.panel > .table-bordered > tfoot > tr > td:last-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; -} - -.panel > .table-bordered > thead > tr:last-child > th, -.panel > .table-responsive > .table-bordered > thead > tr:last-child > th, -.panel > .table-bordered > tbody > tr:last-child > th, -.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, -.panel > .table-bordered > tfoot > tr:last-child > th, -.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th, -.panel > .table-bordered > thead > tr:last-child > td, -.panel > .table-responsive > .table-bordered > thead > tr:last-child > td, -.panel > .table-bordered > tbody > tr:last-child > td, -.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, -.panel > .table-bordered > tfoot > tr:last-child > td, -.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td { - border-bottom: 0; -} - -.panel > .table-responsive { - margin-bottom: 0; - border: 0; -} - -.panel-heading { - padding: 10px 15px; - border-bottom: 1px solid transparent; - border-top-right-radius: 3px; - border-top-left-radius: 3px; -} - -.panel-heading > .dropdown .dropdown-toggle { - color: inherit; -} - -.panel-title { - margin-top: 0; - margin-bottom: 0; - font-size: 16px; - color: inherit; -} - -.panel-title > a { - color: inherit; -} - -.panel-footer { - padding: 10px 15px; - background-color: #f5f5f5; - border-top: 1px solid #dddddd; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} - -.panel-group .panel { - margin-bottom: 0; - overflow: hidden; - border-radius: 4px; -} - -.panel-group .panel + .panel { - margin-top: 5px; -} - -.panel-group .panel-heading { - border-bottom: 0; -} - -.panel-group .panel-heading + .panel-collapse .panel-body { - border-top: 1px solid #dddddd; -} - -.panel-group .panel-footer { - border-top: 0; -} - -.panel-group .panel-footer + .panel-collapse .panel-body { - border-bottom: 1px solid #dddddd; -} - -.panel-default { - border-color: #dddddd; -} - -.panel-default > .panel-heading { - color: #333333; - background-color: #f5f5f5; - border-color: #dddddd; -} - -.panel-default > .panel-heading + .panel-collapse .panel-body { - border-top-color: #dddddd; -} - -.panel-default > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #dddddd; -} - -.panel-primary { - border-color: #428bca; -} - -.panel-primary > .panel-heading { - color: #ffffff; - background-color: #428bca; - border-color: #428bca; -} - -.panel-primary > .panel-heading + .panel-collapse .panel-body { - border-top-color: #428bca; -} - -.panel-primary > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #428bca; -} - -.panel-success { - border-color: #d6e9c6; -} - -.panel-success > .panel-heading { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; -} - -.panel-success > .panel-heading + .panel-collapse .panel-body { - border-top-color: #d6e9c6; -} - -.panel-success > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #d6e9c6; -} - -.panel-warning { - border-color: #faebcc; -} - -.panel-warning > .panel-heading { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; -} - -.panel-warning > .panel-heading + .panel-collapse .panel-body { - border-top-color: #faebcc; -} - -.panel-warning > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #faebcc; -} - -.panel-danger { - border-color: #ebccd1; -} - -.panel-danger > .panel-heading { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; -} - -.panel-danger > .panel-heading + .panel-collapse .panel-body { - border-top-color: #ebccd1; -} - -.panel-danger > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #ebccd1; -} - -.panel-info { - border-color: #bce8f1; -} - -.panel-info > .panel-heading { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; -} - -.panel-info > .panel-heading + .panel-collapse .panel-body { - border-top-color: #bce8f1; -} - -.panel-info > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #bce8f1; -} - -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); -} - -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, 0.15); -} - -.well-lg { - padding: 24px; - border-radius: 6px; -} - -.well-sm { - padding: 9px; - border-radius: 3px; -} - -.close { - float: right; - font-size: 21px; - font-weight: bold; - line-height: 1; - color: #000000; - text-shadow: 0 1px 0 #ffffff; - opacity: 0.2; - filter: alpha(opacity=20); -} - -.close:hover, -.close:focus { - color: #000000; - text-decoration: none; - cursor: pointer; - opacity: 0.5; - filter: alpha(opacity=50); -} - -button.close { - padding: 0; - cursor: pointer; - background: transparent; - border: 0; - -webkit-appearance: none; -} - -.modal-open { - overflow: hidden; -} - -.modal { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - display: none; - overflow: auto; - overflow-y: scroll; -} - -.modal.fade .modal-dialog { - -webkit-transform: translate(0, -25%); - -ms-transform: translate(0, -25%); - transform: translate(0, -25%); - -webkit-transition: -webkit-transform 0.3s ease-out; - -moz-transition: -moz-transform 0.3s ease-out; - -o-transition: -o-transform 0.3s ease-out; - transition: transform 0.3s ease-out; -} - -.modal.in .modal-dialog { - -webkit-transform: translate(0, 0); - -ms-transform: translate(0, 0); - transform: translate(0, 0); -} - -.modal-dialog { - position: relative; - z-index: 1050; - width: auto; - margin: 10px; -} - -.modal-content { - position: relative; - background-color: #ffffff; - border: 1px solid #999999; - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 6px; - outline: none; - -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); - box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); - background-clip: padding-box; -} - -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1030; - background-color: #000000; -} - -.modal-backdrop.fade { - opacity: 0; - filter: alpha(opacity=0); -} - -.modal-backdrop.in { - opacity: 0.5; - filter: alpha(opacity=50); -} - -.modal-header { - min-height: 16.428571429px; - padding: 15px; - border-bottom: 1px solid #e5e5e5; -} - -.modal-header .close { - margin-top: -2px; -} - -.modal-title { - margin: 0; - line-height: 1.428571429; -} - -.modal-body { - position: relative; - padding: 20px; -} - -.modal-footer { - padding: 19px 20px 20px; - margin-top: 15px; - text-align: right; - border-top: 1px solid #e5e5e5; -} - -.modal-footer:before, -.modal-footer:after { - display: table; - content: " "; -} - -.modal-footer:after { - clear: both; -} - -.modal-footer:before, -.modal-footer:after { - display: table; - content: " "; -} - -.modal-footer:after { - clear: both; -} - -.modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; -} - -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} - -.modal-footer .btn-block + .btn-block { - margin-left: 0; -} - -@media screen and (min-width: 768px) { - .modal-dialog { - width: 600px; - margin: 30px auto; - } - .modal-content { - -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); - } -} - -.tooltip { - position: absolute; - z-index: 1030; - display: block; - font-size: 12px; - line-height: 1.4; - opacity: 0; - filter: alpha(opacity=0); - visibility: visible; -} - -.tooltip.in { - opacity: 0.9; - filter: alpha(opacity=90); -} - -.tooltip.top { - padding: 5px 0; - margin-top: -3px; -} - -.tooltip.right { - padding: 0 5px; - margin-left: 3px; -} - -.tooltip.bottom { - padding: 5px 0; - margin-top: 3px; -} - -.tooltip.left { - padding: 0 5px; - margin-left: -3px; -} - -.tooltip-inner { - max-width: 200px; - padding: 3px 8px; - color: #ffffff; - text-align: center; - text-decoration: none; - background-color: #000000; - border-radius: 4px; -} - -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} - -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-top-color: #000000; - border-width: 5px 5px 0; -} - -.tooltip.top-left .tooltip-arrow { - bottom: 0; - left: 5px; - border-top-color: #000000; - border-width: 5px 5px 0; -} - -.tooltip.top-right .tooltip-arrow { - right: 5px; - bottom: 0; - border-top-color: #000000; - border-width: 5px 5px 0; -} - -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-right-color: #000000; - border-width: 5px 5px 5px 0; -} - -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-left-color: #000000; - border-width: 5px 0 5px 5px; -} - -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-bottom-color: #000000; - border-width: 0 5px 5px; -} - -.tooltip.bottom-left .tooltip-arrow { - top: 0; - left: 5px; - border-bottom-color: #000000; - border-width: 0 5px 5px; -} - -.tooltip.bottom-right .tooltip-arrow { - top: 0; - right: 5px; - border-bottom-color: #000000; - border-width: 0 5px 5px; -} - -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1010; - display: none; - max-width: 276px; - padding: 1px; - text-align: left; - white-space: normal; - background-color: #ffffff; - border: 1px solid #cccccc; - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); - background-clip: padding-box; -} - -.popover.top { - margin-top: -10px; -} - -.popover.right { - margin-left: 10px; -} - -.popover.bottom { - margin-top: 10px; -} - -.popover.left { - margin-left: -10px; -} - -.popover-title { - padding: 8px 14px; - margin: 0; - font-size: 14px; - font-weight: normal; - line-height: 18px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - border-radius: 5px 5px 0 0; -} - -.popover-content { - padding: 9px 14px; -} - -.popover .arrow, -.popover .arrow:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} - -.popover .arrow { - border-width: 11px; -} - -.popover .arrow:after { - border-width: 10px; - content: ""; -} - -.popover.top .arrow { - bottom: -11px; - left: 50%; - margin-left: -11px; - border-top-color: #999999; - border-top-color: rgba(0, 0, 0, 0.25); - border-bottom-width: 0; -} - -.popover.top .arrow:after { - bottom: 1px; - margin-left: -10px; - border-top-color: #ffffff; - border-bottom-width: 0; - content: " "; -} - -.popover.right .arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-right-color: #999999; - border-right-color: rgba(0, 0, 0, 0.25); - border-left-width: 0; -} - -.popover.right .arrow:after { - bottom: -10px; - left: 1px; - border-right-color: #ffffff; - border-left-width: 0; - content: " "; -} - -.popover.bottom .arrow { - top: -11px; - left: 50%; - margin-left: -11px; - border-bottom-color: #999999; - border-bottom-color: rgba(0, 0, 0, 0.25); - border-top-width: 0; -} - -.popover.bottom .arrow:after { - top: 1px; - margin-left: -10px; - border-bottom-color: #ffffff; - border-top-width: 0; - content: " "; -} - -.popover.left .arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-left-color: #999999; - border-left-color: rgba(0, 0, 0, 0.25); - border-right-width: 0; -} - -.popover.left .arrow:after { - right: 1px; - bottom: -10px; - border-left-color: #ffffff; - border-right-width: 0; - content: " "; -} - -.carousel { - position: relative; -} - -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden; -} - -.carousel-inner > .item { - position: relative; - display: none; - -webkit-transition: 0.6s ease-in-out left; - transition: 0.6s ease-in-out left; -} - -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - display: block; - height: auto; - max-width: 100%; - line-height: 1; -} - -.carousel-inner > .active, -.carousel-inner > .next, -.carousel-inner > .prev { - display: block; -} - -.carousel-inner > .active { - left: 0; -} - -.carousel-inner > .next, -.carousel-inner > .prev { - position: absolute; - top: 0; - width: 100%; -} - -.carousel-inner > .next { - left: 100%; -} - -.carousel-inner > .prev { - left: -100%; -} - -.carousel-inner > .next.left, -.carousel-inner > .prev.right { - left: 0; -} - -.carousel-inner > .active.left { - left: -100%; -} - -.carousel-inner > .active.right { - left: 100%; -} - -.carousel-control { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 15%; - font-size: 20px; - color: #ffffff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); - opacity: 0.5; - filter: alpha(opacity=50); -} - -.carousel-control.left { - background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.5) 0), color-stop(rgba(0, 0, 0, 0.0001) 100%)); - background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0, rgba(0, 0, 0, 0.0001) 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); -} - -.carousel-control.right { - right: 0; - left: auto; - background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.0001) 0), color-stop(rgba(0, 0, 0, 0.5) 100%)); - background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0, rgba(0, 0, 0, 0.5) 100%); - background-repeat: repeat-x; - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); -} - -.carousel-control:hover, -.carousel-control:focus { - color: #ffffff; - text-decoration: none; - outline: none; - opacity: 0.9; - filter: alpha(opacity=90); -} - -.carousel-control .icon-prev, -.carousel-control .icon-next, -.carousel-control .glyphicon-chevron-left, -.carousel-control .glyphicon-chevron-right { - position: absolute; - top: 50%; - z-index: 5; - display: inline-block; -} - -.carousel-control .icon-prev, -.carousel-control .glyphicon-chevron-left { - left: 50%; -} - -.carousel-control .icon-next, -.carousel-control .glyphicon-chevron-right { - right: 50%; -} - -.carousel-control .icon-prev, -.carousel-control .icon-next { - width: 20px; - height: 20px; - margin-top: -10px; - margin-left: -10px; - font-family: serif; -} - -.carousel-control .icon-prev:before { - content: '\2039'; -} - -.carousel-control .icon-next:before { - content: '\203a'; -} - -.carousel-indicators { - position: absolute; - bottom: 10px; - left: 50%; - z-index: 15; - width: 60%; - padding-left: 0; - margin-left: -30%; - text-align: center; - list-style: none; -} - -.carousel-indicators li { - display: inline-block; - width: 10px; - height: 10px; - margin: 1px; - text-indent: -999px; - cursor: pointer; - background-color: #000 \9; - background-color: rgba(0, 0, 0, 0); - border: 1px solid #ffffff; - border-radius: 10px; -} - -.carousel-indicators .active { - width: 12px; - height: 12px; - margin: 0; - background-color: #ffffff; -} - -.carousel-caption { - position: absolute; - right: 15%; - bottom: 20px; - left: 15%; - z-index: 10; - padding-top: 20px; - padding-bottom: 20px; - color: #ffffff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); -} - -.carousel-caption .btn { - text-shadow: none; -} - -@media screen and (min-width: 768px) { - .carousel-control .glyphicons-chevron-left, - .carousel-control .glyphicons-chevron-right, - .carousel-control .icon-prev, - .carousel-control .icon-next { - width: 30px; - height: 30px; - margin-top: -15px; - margin-left: -15px; - font-size: 30px; - } - .carousel-caption { - right: 20%; - left: 20%; - padding-bottom: 30px; - } - .carousel-indicators { - bottom: 20px; - } -} - -.clearfix:before, -.clearfix:after { - display: table; - content: " "; -} - -.clearfix:after { - clear: both; -} - -.center-block { - display: block; - margin-right: auto; - margin-left: auto; -} - -.pull-right { - float: right !important; -} - -.pull-left { - float: left !important; -} - -.hide { - display: none !important; -} - -.show { - display: block !important; -} - -.invisible { - visibility: hidden; -} - -.text-hide { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} - -.hidden { - display: none !important; - visibility: hidden !important; -} - -.affix { - position: fixed; -} - -@-ms-viewport { - width: device-width; -} - -.visible-xs, -tr.visible-xs, -th.visible-xs, -td.visible-xs { - display: none !important; -} - -@media (max-width: 767px) { - .visible-xs { - display: block !important; - } - table.visible-xs { - display: table; - } - tr.visible-xs { - display: table-row !important; - } - th.visible-xs, - td.visible-xs { - display: table-cell !important; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .visible-xs.visible-sm { - display: block !important; - } - table.visible-xs.visible-sm { - display: table; - } - tr.visible-xs.visible-sm { - display: table-row !important; - } - th.visible-xs.visible-sm, - td.visible-xs.visible-sm { - display: table-cell !important; - } -} - -@media (min-width: 992px) and (max-width: 1199px) { - .visible-xs.visible-md { - display: block !important; - } - table.visible-xs.visible-md { - display: table; - } - tr.visible-xs.visible-md { - display: table-row !important; - } - th.visible-xs.visible-md, - td.visible-xs.visible-md { - display: table-cell !important; - } -} - -@media (min-width: 1200px) { - .visible-xs.visible-lg { - display: block !important; - } - table.visible-xs.visible-lg { - display: table; - } - tr.visible-xs.visible-lg { - display: table-row !important; - } - th.visible-xs.visible-lg, - td.visible-xs.visible-lg { - display: table-cell !important; - } -} - -.visible-sm, -tr.visible-sm, -th.visible-sm, -td.visible-sm { - display: none !important; -} - -@media (max-width: 767px) { - .visible-sm.visible-xs { - display: block !important; - } - table.visible-sm.visible-xs { - display: table; - } - tr.visible-sm.visible-xs { - display: table-row !important; - } - th.visible-sm.visible-xs, - td.visible-sm.visible-xs { - display: table-cell !important; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm { - display: block !important; - } - table.visible-sm { - display: table; - } - tr.visible-sm { - display: table-row !important; - } - th.visible-sm, - td.visible-sm { - display: table-cell !important; - } -} - -@media (min-width: 992px) and (max-width: 1199px) { - .visible-sm.visible-md { - display: block !important; - } - table.visible-sm.visible-md { - display: table; - } - tr.visible-sm.visible-md { - display: table-row !important; - } - th.visible-sm.visible-md, - td.visible-sm.visible-md { - display: table-cell !important; - } -} - -@media (min-width: 1200px) { - .visible-sm.visible-lg { - display: block !important; - } - table.visible-sm.visible-lg { - display: table; - } - tr.visible-sm.visible-lg { - display: table-row !important; - } - th.visible-sm.visible-lg, - td.visible-sm.visible-lg { - display: table-cell !important; - } -} - -.visible-md, -tr.visible-md, -th.visible-md, -td.visible-md { - display: none !important; -} - -@media (max-width: 767px) { - .visible-md.visible-xs { - display: block !important; - } - table.visible-md.visible-xs { - display: table; - } - tr.visible-md.visible-xs { - display: table-row !important; - } - th.visible-md.visible-xs, - td.visible-md.visible-xs { - display: table-cell !important; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .visible-md.visible-sm { - display: block !important; - } - table.visible-md.visible-sm { - display: table; - } - tr.visible-md.visible-sm { - display: table-row !important; - } - th.visible-md.visible-sm, - td.visible-md.visible-sm { - display: table-cell !important; - } -} - -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md { - display: block !important; - } - table.visible-md { - display: table; - } - tr.visible-md { - display: table-row !important; - } - th.visible-md, - td.visible-md { - display: table-cell !important; - } -} - -@media (min-width: 1200px) { - .visible-md.visible-lg { - display: block !important; - } - table.visible-md.visible-lg { - display: table; - } - tr.visible-md.visible-lg { - display: table-row !important; - } - th.visible-md.visible-lg, - td.visible-md.visible-lg { - display: table-cell !important; - } -} - -.visible-lg, -tr.visible-lg, -th.visible-lg, -td.visible-lg { - display: none !important; -} - -@media (max-width: 767px) { - .visible-lg.visible-xs { - display: block !important; - } - table.visible-lg.visible-xs { - display: table; - } - tr.visible-lg.visible-xs { - display: table-row !important; - } - th.visible-lg.visible-xs, - td.visible-lg.visible-xs { - display: table-cell !important; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .visible-lg.visible-sm { - display: block !important; - } - table.visible-lg.visible-sm { - display: table; - } - tr.visible-lg.visible-sm { - display: table-row !important; - } - th.visible-lg.visible-sm, - td.visible-lg.visible-sm { - display: table-cell !important; - } -} - -@media (min-width: 992px) and (max-width: 1199px) { - .visible-lg.visible-md { - display: block !important; - } - table.visible-lg.visible-md { - display: table; - } - tr.visible-lg.visible-md { - display: table-row !important; - } - th.visible-lg.visible-md, - td.visible-lg.visible-md { - display: table-cell !important; - } -} - -@media (min-width: 1200px) { - .visible-lg { - display: block !important; - } - table.visible-lg { - display: table; - } - tr.visible-lg { - display: table-row !important; - } - th.visible-lg, - td.visible-lg { - display: table-cell !important; - } -} - -.hidden-xs { - display: block !important; -} - -table.hidden-xs { - display: table; -} - -tr.hidden-xs { - display: table-row !important; -} - -th.hidden-xs, -td.hidden-xs { - display: table-cell !important; -} - -@media (max-width: 767px) { - .hidden-xs, - tr.hidden-xs, - th.hidden-xs, - td.hidden-xs { - display: none !important; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .hidden-xs.hidden-sm, - tr.hidden-xs.hidden-sm, - th.hidden-xs.hidden-sm, - td.hidden-xs.hidden-sm { - display: none !important; - } -} - -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-xs.hidden-md, - tr.hidden-xs.hidden-md, - th.hidden-xs.hidden-md, - td.hidden-xs.hidden-md { - display: none !important; - } -} - -@media (min-width: 1200px) { - .hidden-xs.hidden-lg, - tr.hidden-xs.hidden-lg, - th.hidden-xs.hidden-lg, - td.hidden-xs.hidden-lg { - display: none !important; - } -} - -.hidden-sm { - display: block !important; -} - -table.hidden-sm { - display: table; -} - -tr.hidden-sm { - display: table-row !important; -} - -th.hidden-sm, -td.hidden-sm { - display: table-cell !important; -} - -@media (max-width: 767px) { - .hidden-sm.hidden-xs, - tr.hidden-sm.hidden-xs, - th.hidden-sm.hidden-xs, - td.hidden-sm.hidden-xs { - display: none !important; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .hidden-sm, - tr.hidden-sm, - th.hidden-sm, - td.hidden-sm { - display: none !important; - } -} - -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-sm.hidden-md, - tr.hidden-sm.hidden-md, - th.hidden-sm.hidden-md, - td.hidden-sm.hidden-md { - display: none !important; - } -} - -@media (min-width: 1200px) { - .hidden-sm.hidden-lg, - tr.hidden-sm.hidden-lg, - th.hidden-sm.hidden-lg, - td.hidden-sm.hidden-lg { - display: none !important; - } -} - -.hidden-md { - display: block !important; -} - -table.hidden-md { - display: table; -} - -tr.hidden-md { - display: table-row !important; -} - -th.hidden-md, -td.hidden-md { - display: table-cell !important; -} - -@media (max-width: 767px) { - .hidden-md.hidden-xs, - tr.hidden-md.hidden-xs, - th.hidden-md.hidden-xs, - td.hidden-md.hidden-xs { - display: none !important; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .hidden-md.hidden-sm, - tr.hidden-md.hidden-sm, - th.hidden-md.hidden-sm, - td.hidden-md.hidden-sm { - display: none !important; - } -} - -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-md, - tr.hidden-md, - th.hidden-md, - td.hidden-md { - display: none !important; - } -} - -@media (min-width: 1200px) { - .hidden-md.hidden-lg, - tr.hidden-md.hidden-lg, - th.hidden-md.hidden-lg, - td.hidden-md.hidden-lg { - display: none !important; - } -} - -.hidden-lg { - display: block !important; -} - -table.hidden-lg { - display: table; -} - -tr.hidden-lg { - display: table-row !important; -} - -th.hidden-lg, -td.hidden-lg { - display: table-cell !important; -} - -@media (max-width: 767px) { - .hidden-lg.hidden-xs, - tr.hidden-lg.hidden-xs, - th.hidden-lg.hidden-xs, - td.hidden-lg.hidden-xs { - display: none !important; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .hidden-lg.hidden-sm, - tr.hidden-lg.hidden-sm, - th.hidden-lg.hidden-sm, - td.hidden-lg.hidden-sm { - display: none !important; - } -} - -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-lg.hidden-md, - tr.hidden-lg.hidden-md, - th.hidden-lg.hidden-md, - td.hidden-lg.hidden-md { - display: none !important; - } -} - -@media (min-width: 1200px) { - .hidden-lg, - tr.hidden-lg, - th.hidden-lg, - td.hidden-lg { - display: none !important; - } -} - -.visible-print, -tr.visible-print, -th.visible-print, -td.visible-print { - display: none !important; -} - -@media print { - .visible-print { - display: block !important; - } - table.visible-print { - display: table; - } - tr.visible-print { - display: table-row !important; - } - th.visible-print, - td.visible-print { - display: table-cell !important; - } - .hidden-print, - tr.hidden-print, - th.hidden-print, - td.hidden-print { - display: none !important; - } -} \ No newline at end of file diff --git a/webroot/AutoSa/static/css/bootstrap.min.css b/webroot/AutoSa/static/css/bootstrap.min.css deleted file mode 100644 index c547283bbda8..000000000000 --- a/webroot/AutoSa/static/css/bootstrap.min.css +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap v3.0.3 (http://getbootstrap.com) - * Copyright 2013 Twitter, Inc. - * Licensed under http://www.apache.org/licenses/LICENSE-2.0 - */ - -/*! normalize.css v2.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a{background:transparent}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{margin:.67em 0;font-size:2em}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{height:0;-moz-box-sizing:content-box;box-sizing:content-box}mark{color:#000;background:#ff0}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid #c0c0c0}legend{padding:0;border:0}button,input,select,textarea{margin:0;font-family:inherit;font-size:100%}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{padding:0;box-sizing:border-box}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:2cm .5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}*,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}img{vertical-align:middle}.img-responsive{display:block;height:auto;max-width:100%}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{margin-top:20px;margin-bottom:10px}h1 small,h2 small,h3 small,h1 .small,h2 .small,h3 .small{font-size:65%}h4,h5,h6{margin-top:10px;margin-bottom:10px}h4 small,h5 small,h6 small,h4 .small,h5 .small,h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media(min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-muted{color:#999}.text-primary{color:#428bca}.text-primary:hover{color:#3071a9}.text-warning{color:#8a6d3b}.text-warning:hover{color:#66512c}.text-danger{color:#a94442}.text-danger:hover{color:#843534}.text-success{color:#3c763d}.text-success:hover{color:#2b542c}.text-info{color:#31708f}.text-info:hover{color:#245269}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}.list-inline>li:first-child{padding-left:0}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.428571429}dt{font-weight:bold}dd{margin-left:0}@media(min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:" "}.dl-horizontal dd:after{clear:both}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:" "}.dl-horizontal dd:after{clear:both}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{font-size:17.5px;font-weight:300;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small,blockquote .small{display:block;line-height:1.428571429;color:#999}blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small,blockquote.pull-right .small{text-align:right}blockquote.pull-right small:before,blockquote.pull-right .small:before{content:''}blockquote.pull-right small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.428571429}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;white-space:nowrap;background-color:#f9f2f4;border-radius:4px}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.container:before,.container:after{display:table;content:" "}.container:after{clear:both}.container:before,.container:after{display:table;content:" "}.container:after{clear:both}@media(min-width:768px){.container{width:750px}}@media(min-width:992px){.container{width:970px}}@media(min-width:1200px){.container{width:1170px}}.row{margin-right:-15px;margin-left:-15px}.row:before,.row:after{display:table;content:" "}.row:after{clear:both}.row:before,.row:after{display:table;content:" "}.row:after{clear:both}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666666666666%}.col-xs-10{width:83.33333333333334%}.col-xs-9{width:75%}.col-xs-8{width:66.66666666666666%}.col-xs-7{width:58.333333333333336%}.col-xs-6{width:50%}.col-xs-5{width:41.66666666666667%}.col-xs-4{width:33.33333333333333%}.col-xs-3{width:25%}.col-xs-2{width:16.666666666666664%}.col-xs-1{width:8.333333333333332%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666666666666%}.col-xs-pull-10{right:83.33333333333334%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666666666666%}.col-xs-pull-7{right:58.333333333333336%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666666666667%}.col-xs-pull-4{right:33.33333333333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.666666666666664%}.col-xs-pull-1{right:8.333333333333332%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666666666666%}.col-xs-push-10{left:83.33333333333334%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666666666666%}.col-xs-push-7{left:58.333333333333336%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666666666667%}.col-xs-push-4{left:33.33333333333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.666666666666664%}.col-xs-push-1{left:8.333333333333332%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666666666666%}.col-xs-offset-10{margin-left:83.33333333333334%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666666666666%}.col-xs-offset-7{margin-left:58.333333333333336%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666666666667%}.col-xs-offset-4{margin-left:33.33333333333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.666666666666664%}.col-xs-offset-1{margin-left:8.333333333333332%}.col-xs-offset-0{margin-left:0}@media(min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media(min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media(min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*="col-"]{position:static;display:table-column;float:none}table td[class*="col-"],table th[class*="col-"]{display:table-cell;float:none}.table>thead>tr>.active,.table>tbody>tr>.active,.table>tfoot>tr>.active,.table>thead>.active>td,.table>tbody>.active>td,.table>tfoot>.active>td,.table>thead>.active>th,.table>tbody>.active>th,.table>tfoot>.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>.active:hover,.table-hover>tbody>.active:hover>td,.table-hover>tbody>.active:hover>th{background-color:#e8e8e8}.table>thead>tr>.success,.table>tbody>tr>.success,.table>tfoot>tr>.success,.table>thead>.success>td,.table>tbody>.success>td,.table>tfoot>.success>td,.table>thead>.success>th,.table>tbody>.success>th,.table>tfoot>.success>th{background-color:#dff0d8}.table-hover>tbody>tr>.success:hover,.table-hover>tbody>.success:hover>td,.table-hover>tbody>.success:hover>th{background-color:#d0e9c6}.table>thead>tr>.danger,.table>tbody>tr>.danger,.table>tfoot>tr>.danger,.table>thead>.danger>td,.table>tbody>.danger>td,.table>tfoot>.danger>td,.table>thead>.danger>th,.table>tbody>.danger>th,.table>tfoot>.danger>th{background-color:#f2dede}.table-hover>tbody>tr>.danger:hover,.table-hover>tbody>.danger:hover>td,.table-hover>tbody>.danger:hover>th{background-color:#ebcccc}.table>thead>tr>.warning,.table>tbody>tr>.warning,.table>tfoot>tr>.warning,.table>thead>.warning>td,.table>tbody>.warning>td,.table>tfoot>.warning>td,.table>thead>.warning>th,.table>tbody>.warning>th,.table>tfoot>.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>.warning:hover,.table-hover>tbody>.warning:hover>td,.table-hover>tbody>.warning:hover>th{background-color:#faf2cc}@media(max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:scroll;overflow-y:hidden;border:1px solid #ddd;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}select[multiple],select[size]{height:auto}select optgroup{font-family:inherit;font-size:inherit;font-style:inherit}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}input[type="number"]::-webkit-outer-spin-button,input[type="number"]::-webkit-inner-spin-button{height:auto}output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee}textarea.form-control{height:auto}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;padding-left:20px;margin-top:10px;margin-bottom:10px;vertical-align:middle}.radio label,.checkbox label{display:inline;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:normal;vertical-align:middle;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg{height:auto}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media(min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block}.form-inline select.form-control{width:auto}.form-inline .radio,.form-inline .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:" "}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:" "}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-control-static{padding-top:7px}@media(min-width:768px){.form-horizontal .control-label{text-align:right}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:normal;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#fff}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-link{font-weight:normal;color:#428bca;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:normal;line-height:1;-moz-osx-font-smoothing:grayscale}.glyphicon:empty{width:1em}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.428571429;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#428bca;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media(min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar:before,.btn-toolbar:after{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar:before,.btn-toolbar:after{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar .btn-group{float:left}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group,.btn-toolbar>.btn-group+.btn-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-bottom-left-radius:4px;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child>.btn:last-child,.btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;border-collapse:separate;table-layout:fixed}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}[data-toggle="buttons"]>.btn>input[type="radio"],[data-toggle="buttons"]>.btn>input[type="checkbox"]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-right:0;padding-left:0}.input-group .form-control{width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;white-space:nowrap}.input-group-btn:first-child>.btn{margin-right:-1px}.input-group-btn:last-child>.btn{margin-left:-1px}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-4px}.input-group-btn>.btn:hover,.input-group-btn>.btn:active{z-index:2}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav:before,.nav:after{display:table;content:" "}.nav:after{clear:both}.nav:before,.nav:after{display:table;content:" "}.nav:after{clear:both}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media(min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media(min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media(min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media(min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}.navbar:before,.navbar:after{display:table;content:" "}.navbar:after{clear:both}.navbar:before,.navbar:after{display:table;content:" "}.navbar:after{clear:both}@media(min-width:768px){.navbar{border-radius:4px}}.navbar-header:before,.navbar-header:after{display:table;content:" "}.navbar-header:after{clear:both}.navbar-header:before,.navbar-header:after{display:table;content:" "}.navbar-header:after{clear:both}@media(min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse:before,.navbar-collapse:after{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse:before,.navbar-collapse:after{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse.in{overflow-y:auto}@media(min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-right:0;padding-left:0}}.container>.navbar-header,.container>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media(min-width:768px){.container>.navbar-header,.container>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media(min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media(min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media(min-width:768px){.navbar>.container .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media(min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media(max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media(min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media(min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}@media(min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block}.navbar-form select.form-control{width:auto}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{float:none;margin-left:0}}@media(max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media(min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-nav.pull-right>li>.dropdown-menu,.navbar-nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media(min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#ccc}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}@media(max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}@media(max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.428571429;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#eee}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;cursor:default;background-color:#428bca;border-color:#428bca}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager:before,.pager:after{display:table;content:" "}.pager:after{clear:both}.pager:before,.pager:after{display:table;content:" "}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#999;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;font-size:21px;font-weight:200;line-height:2.1428571435;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{line-height:1;color:inherit}.jumbotron p{line-height:1.4}.container .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img,.thumbnail a>img{display:block;height:auto;max-width:100%;margin-right:auto;margin-left:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-body:before,.panel-body:after{display:table;content:" "}.panel-body:after{clear:both}.panel-body:before,.panel-body:after{display:table;content:" "}.panel-body:after{clear:both}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0}.panel>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child th,.panel>.table>tbody:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:last-child>th,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:last-child>td,.panel>.table-responsive>.table-bordered>thead>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-group .panel{margin-bottom:0;overflow:hidden;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;display:none;overflow:auto;overflow-y:scroll}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{position:relative;z-index:1050;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{min-height:16.428571429px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:20px}.modal-footer{padding:19px 20px 20px;margin-top:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer:before,.modal-footer:after{display:table;content:" "}.modal-footer:after{clear:both}.modal-footer:before,.modal-footer:after{display:table;content:" "}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media screen and (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}}.tooltip{position:absolute;z-index:1030;display:block;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0;content:" "}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0;content:" "}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0;content:" "}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0;content:" "}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;height:auto;max-width:100%;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);opacity:.5;filter:alpha(opacity=50)}.carousel-control.left{background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.5) 0),color-stop(rgba(0,0,0,0.0001) 100%));background-image:linear-gradient(to right,rgba(0,0,0,0.5) 0,rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000',endColorstr='#00000000',GradientType=1)}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.0001) 0),color-stop(rgba(0,0,0,0.5) 100%));background-image:linear-gradient(to right,rgba(0,0,0,0.0001) 0,rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000',endColorstr='#80000000',GradientType=1)}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;outline:0;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicons-chevron-left,.carousel-control .glyphicons-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after{display:table;content:" "}.clearfix:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,tr.visible-xs,th.visible-xs,td.visible-xs{display:none!important}@media(max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block!important}table.visible-xs.visible-sm{display:table}tr.visible-xs.visible-sm{display:table-row!important}th.visible-xs.visible-sm,td.visible-xs.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-xs.visible-md{display:block!important}table.visible-xs.visible-md{display:table}tr.visible-xs.visible-md{display:table-row!important}th.visible-xs.visible-md,td.visible-xs.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-xs.visible-lg{display:block!important}table.visible-xs.visible-lg{display:table}tr.visible-xs.visible-lg{display:table-row!important}th.visible-xs.visible-lg,td.visible-xs.visible-lg{display:table-cell!important}}.visible-sm,tr.visible-sm,th.visible-sm,td.visible-sm{display:none!important}@media(max-width:767px){.visible-sm.visible-xs{display:block!important}table.visible-sm.visible-xs{display:table}tr.visible-sm.visible-xs{display:table-row!important}th.visible-sm.visible-xs,td.visible-sm.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-sm.visible-md{display:block!important}table.visible-sm.visible-md{display:table}tr.visible-sm.visible-md{display:table-row!important}th.visible-sm.visible-md,td.visible-sm.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-sm.visible-lg{display:block!important}table.visible-sm.visible-lg{display:table}tr.visible-sm.visible-lg{display:table-row!important}th.visible-sm.visible-lg,td.visible-sm.visible-lg{display:table-cell!important}}.visible-md,tr.visible-md,th.visible-md,td.visible-md{display:none!important}@media(max-width:767px){.visible-md.visible-xs{display:block!important}table.visible-md.visible-xs{display:table}tr.visible-md.visible-xs{display:table-row!important}th.visible-md.visible-xs,td.visible-md.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block!important}table.visible-md.visible-sm{display:table}tr.visible-md.visible-sm{display:table-row!important}th.visible-md.visible-sm,td.visible-md.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-md.visible-lg{display:block!important}table.visible-md.visible-lg{display:table}tr.visible-md.visible-lg{display:table-row!important}th.visible-md.visible-lg,td.visible-md.visible-lg{display:table-cell!important}}.visible-lg,tr.visible-lg,th.visible-lg,td.visible-lg{display:none!important}@media(max-width:767px){.visible-lg.visible-xs{display:block!important}table.visible-lg.visible-xs{display:table}tr.visible-lg.visible-xs{display:table-row!important}th.visible-lg.visible-xs,td.visible-lg.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block!important}table.visible-lg.visible-sm{display:table}tr.visible-lg.visible-sm{display:table-row!important}th.visible-lg.visible-sm,td.visible-lg.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-lg.visible-md{display:block!important}table.visible-lg.visible-md{display:table}tr.visible-lg.visible-md{display:table-row!important}th.visible-lg.visible-md,td.visible-lg.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}.hidden-xs{display:block!important}table.hidden-xs{display:table}tr.hidden-xs{display:table-row!important}th.hidden-xs,td.hidden-xs{display:table-cell!important}@media(max-width:767px){.hidden-xs,tr.hidden-xs,th.hidden-xs,td.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm,tr.hidden-xs.hidden-sm,th.hidden-xs.hidden-sm,td.hidden-xs.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-xs.hidden-md,tr.hidden-xs.hidden-md,th.hidden-xs.hidden-md,td.hidden-xs.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-xs.hidden-lg,tr.hidden-xs.hidden-lg,th.hidden-xs.hidden-lg,td.hidden-xs.hidden-lg{display:none!important}}.hidden-sm{display:block!important}table.hidden-sm{display:table}tr.hidden-sm{display:table-row!important}th.hidden-sm,td.hidden-sm{display:table-cell!important}@media(max-width:767px){.hidden-sm.hidden-xs,tr.hidden-sm.hidden-xs,th.hidden-sm.hidden-xs,td.hidden-sm.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-sm,tr.hidden-sm,th.hidden-sm,td.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-sm.hidden-md,tr.hidden-sm.hidden-md,th.hidden-sm.hidden-md,td.hidden-sm.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-sm.hidden-lg,tr.hidden-sm.hidden-lg,th.hidden-sm.hidden-lg,td.hidden-sm.hidden-lg{display:none!important}}.hidden-md{display:block!important}table.hidden-md{display:table}tr.hidden-md{display:table-row!important}th.hidden-md,td.hidden-md{display:table-cell!important}@media(max-width:767px){.hidden-md.hidden-xs,tr.hidden-md.hidden-xs,th.hidden-md.hidden-xs,td.hidden-md.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-md.hidden-sm,tr.hidden-md.hidden-sm,th.hidden-md.hidden-sm,td.hidden-md.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-md,tr.hidden-md,th.hidden-md,td.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-md.hidden-lg,tr.hidden-md.hidden-lg,th.hidden-md.hidden-lg,td.hidden-md.hidden-lg{display:none!important}}.hidden-lg{display:block!important}table.hidden-lg{display:table}tr.hidden-lg{display:table-row!important}th.hidden-lg,td.hidden-lg{display:table-cell!important}@media(max-width:767px){.hidden-lg.hidden-xs,tr.hidden-lg.hidden-xs,th.hidden-lg.hidden-xs,td.hidden-lg.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-lg.hidden-sm,tr.hidden-lg.hidden-sm,th.hidden-lg.hidden-sm,td.hidden-lg.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-lg.hidden-md,tr.hidden-lg.hidden-md,th.hidden-lg.hidden-md,td.hidden-lg.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-lg,tr.hidden-lg,th.hidden-lg,td.hidden-lg{display:none!important}}.visible-print,tr.visible-print,th.visible-print,td.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}.hidden-print,tr.hidden-print,th.hidden-print,td.hidden-print{display:none!important}} \ No newline at end of file diff --git a/webroot/AutoSa/static/css/docs.css b/webroot/AutoSa/static/css/docs.css deleted file mode 100644 index 368053950bd2..000000000000 --- a/webroot/AutoSa/static/css/docs.css +++ /dev/null @@ -1,1198 +0,0 @@ -/*! - * Copyright 2013 Twitter, Inc. - * - * Licensed under the Creative Commons Attribution 3.0 Unported License. For - * details, see http://creativecommons.org/licenses/by/3.0/. - */ - - -/* - * Bootstrap Documentation - * Special styles for presenting Bootstrap's documentation and code examples. - * - * Table of contents: - * - * Scaffolding - * Main navigation - * Footer - * Social buttons - * Homepage - * Page headers - * Old docs callout - * Ads - * Side navigation - * Docs sections - * Callouts - * Grid styles - * Examples - * Code snippets (highlight) - * Responsive tests - * Glyphicons - * Customizer - * Miscellaneous - */ - - -/* - * Scaffolding - * - * Update the basics of our documents to prep for docs content. - */ - -body { - position: relative; /* For scrollyspy */ - padding-top: 50px; /* Account for fixed navbar */ -} - -/* Keep code small in tables on account of limited space */ -.table code { - font-size: 13px; - font-weight: normal; -} - -/* Outline button for use within the docs */ -.btn-outline { - color: #563d7c; - background-color: #fff; - border-color: #e5e5e5; -} -.btn-outline:hover, -.btn-outline:focus, -.btn-outline:active { - color: #fff; - background-color: #563d7c; - border-color: #563d7c; -} - -/* Inverted outline button (white on dark) */ -.btn-outline-inverse { - color: #fff; - background-color: transparent; - border-color: #cdbfe3; -} -.btn-outline-inverse:hover, -.btn-outline-inverse:focus, -.btn-outline-inverse:active { - color: #563d7c; - text-shadow: none; - background-color: #fff; - border-color: #fff; -} - - -/* - * Main navigation - * - * Turn the `.navbar` at the top of the docs purple. - */ - -.bs-docs-nav { - text-shadow: 0 -1px 0 rgba(0,0,0,.15); - background-color: #563d7c; - border-color: #463265; - box-shadow: 0 1px 0 rgba(255,255,255,.1); -} -.bs-docs-nav .navbar-collapse { - border-color: #463265; -} -.bs-docs-nav .navbar-brand { - color: #fff; -} -.bs-docs-nav .navbar-nav > li > a { - color: #cdbfe3; -} -.bs-docs-nav .navbar-nav > li > a:hover { - color: #fff; -} -.bs-docs-nav .navbar-nav > .active > a, -.bs-docs-nav .navbar-nav > .active > a:hover { - color: #fff; - background-color: #463265; -} -.bs-docs-nav .navbar-toggle { - border-color: #563d7c; -} -.bs-docs-nav .navbar-toggle:hover { - background-color: #463265; - border-color: #463265; -} - - -/* - * Footer - * - * Separated section of content at the bottom of all pages, save the homepage. - */ - -.bs-footer { - padding-top: 40px; - padding-bottom: 30px; - margin-top: 100px; - color: #777; - text-align: center; - border-top: 1px solid #e5e5e5; -} -.footer-links { - margin: 10px 0; - padding-left: 0; -} -.footer-links li { - display: inline; - padding: 0 2px; -} -.footer-links li:first-child { - padding-left: 0; -} - -@media (min-width: 768px) { - .bs-footer { - text-align: left; - } - .bs-footer p { - margin-bottom: 0; - } -} - - -/* - * Social buttons - * - * Twitter and GitHub social action buttons (for homepage and footer). - */ - -.bs-social { - margin-top: 20px; - margin-bottom: 20px; - text-align: center; -} -.bs-social-buttons { - display: inline-block; - margin-bottom: 0; - padding-left: 0; - list-style: none; -} -.bs-social-buttons li { - display: inline-block; - line-height: 1; - padding: 5px 8px; -} -.bs-social-buttons .twitter-follow-button { - width: 225px !important; -} -.bs-social-buttons .twitter-share-button { - width: 98px !important; -} -/* Style the GitHub buttons via CSS instead of inline attributes */ -.github-btn { - border: 0; - overflow: hidden; -} - -@media (min-width: 768px) { - .bs-social { - text-align: left; - } - .bs-social-buttons li:first-child { - padding-left: 0; - } -} - - -/* - * Topography, yo! - * - * Apply the map background via base64 and relevant colors where we need 'em. - */ - -.bs-docs-home, -.bs-header { - color: #cdbfe3; - background-color: #563d7c; - background-image: url(data:image/png;base64,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); -} - - -/* - * Homepage - * - * Tweaks to the custom homepage and the masthead (main jumbotron). - */ - - /* Masthead (headings and download button) */ - .bs-masthead { - position: relative; - padding: 30px 15px; - text-align: center; - text-shadow: 0 1px 0 rgba(0,0,0,.15); -} -.bs-masthead h1 { - font-size: 50px; - line-height: 1; - color: #fff; -} -.bs-masthead .btn-outline-inverse { - margin: 10px; -} - -/* Links to project-level content like the repo, Expo, etc */ -.bs-masthead-links { - margin-top: 20px; - margin-bottom: 40px; - padding: 0 15px; - list-style: none; - text-align: center; -} -.bs-masthead-links li { - display: inline; -} -.bs-masthead-links li + li { - margin-left: 20px; -} -.bs-masthead-links a { - color: #fff; -} - -@media (min-width: 768px) { - .bs-masthead { - text-align: left; - padding-top: 140px; - padding-bottom: 140px; - } - .bs-masthead h1 { - font-size: 100px; - } - .bs-masthead .lead { - margin-right: 25%; - font-size: 30px; - } - .bs-masthead .btn-outline-inverse { - width: auto; - margin: 20px 5px 20px 0; - padding: 18px 24px; - font-size: 21px; - } - .bs-masthead-links { - padding: 0; - text-align: left; - } -} - - -/* - * Page headers - * - * Jumbotron-esque headers at the top of every page that's not the homepage. - */ - - -/* Page headers */ -.bs-header { - padding: 30px 15px 40px; /* side padding builds on .container 15px, so 30px */ - font-size: 16px; - text-align: center; - text-shadow: 0 1px 0 rgba(0,0,0,.15); -} -.bs-header h1 { - color: #fff; -} -.bs-header p { - font-weight: 300; - line-height: 1.5; -} -.bs-header .container { - position: relative; -} - -@media (min-width: 768px) { - .bs-header { - font-size: 21px; - text-align: left; - } - .bs-header h1 { - font-size: 60px; - line-height: 1; - } -} - -@media (min-width: 992px) { - .bs-header h1, - .bs-header p { - margin-right: 380px; - } -} - - -/* - * Carbon ads - * - * Single display ad that shows on all pages (except homepage) in page headers. - * The hella `!important` is required for any pre-set property. - */ - -.carbonad { - width: auto !important; - margin: 50px -30px -40px !important; - padding: 20px !important; - overflow: hidden; /* clearfix */ - height: auto !important; - font-size: 13px !important; - line-height: 16px !important; - text-align: left; - background: #463265 !important; - border: 0 !important; - box-shadow: inset 0 3px 5px rgba(0,0,0,.075); -} -.carbonad-img { - margin: 0 !important; -} -.carbonad-text, -.carbonad-tag { - float: none !important; - display: block !important; - width: auto !important; - height: auto !important; - margin-left: 145px !important; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif !important; -} -.carbonad-text { - padding-top: 0 !important; -} -.carbonad-tag { - color: #cdbfe3 !important; - text-align: left !important; -} -.carbonad-text a, -.carbonad-tag a { - color: #fff !important; -} -.carbonad #azcarbon > img { - display: none; /* hide what I assume are tracking images */ -} - -@media (min-width: 768px) { - .carbonad { - margin: 0 !important; - border-radius: 4px; - box-shadow: inset 0 3px 5px rgba(0,0,0,.075), 0 1px 0 rgba(255,255,255,.1); - } -} - -@media (min-width: 992px) { - .carbonad { - position: absolute; - top: 20px; - right: 15px; /* 15px instead of 0 since box-sizing */ - padding: 15px !important; - width: 330px !important; - } -} - -/* Homepage variations */ -.bs-docs-home .carbonad { - margin: 0 -15px 40px !important; -} -@media (min-width: 480px) { - .bs-docs-home .carbonad { - width: 330px !important; - margin: 0 auto 40px !important; - border-radius: 4px; - } -} -@media (min-width: 768px) { - .bs-docs-home .carbonad { - float: left; - width: 330px !important; - margin: 0 0 30px !important; - } - .bs-docs-home .bs-social, - .bs-docs-home .bs-masthead-links { - margin-left: 350px; - } - .bs-docs-home .bs-social { - margin-bottom: 10px; - } - .bs-docs-home .bs-masthead-links { - margin-top: 10px; - } -} -@media (min-width: 992px) { - .bs-docs-home .carbonad { - position: static; - } -} -@media (min-width: 1170px) { - .bs-docs-home .carbonad { - margin-top: -25px !important; - } -} - - -/* - * Callout for 2.3.2 docs - * - * Only appears below page headers (not on the homepage). The homepage gets its - * own link with the masthead links. - */ - -.bs-old-docs { - padding: 15px 20px; - color: #777; - background-color: #fafafa; - border-top: 1px solid #fff; - border-bottom: 1px solid #e5e5e5; -} -.bs-old-docs strong { - color: #555; -} - - -/* - * Side navigation - * - * Scrollspy and affixed enhanced navigation to highlight sections and secondary - * sections of docs content. - */ - -/* By default it's not affixed in mobile views, so undo that */ -.bs-sidebar.affix { - position: static; -} - -/* First level of nav */ -.bs-sidenav { - margin-top: 30px; - margin-bottom: 30px; - padding-top: 10px; - padding-bottom: 10px; - text-shadow: 0 1px 0 #fff; - background-color: #f7f5fa; - border-radius: 5px; -} - -/* All levels of nav */ -.bs-sidebar .nav > li > a { - display: block; - color: #716b7a; - padding: 5px 20px; -} -.bs-sidebar .nav > li > a:hover, -.bs-sidebar .nav > li > a:focus { - text-decoration: none; - background-color: #e5e3e9; - border-right: 1px solid #dbd8e0; -} -.bs-sidebar .nav > .active > a, -.bs-sidebar .nav > .active:hover > a, -.bs-sidebar .nav > .active:focus > a { - font-weight: bold; - color: #563d7c; - background-color: transparent; - border-right: 1px solid #563d7c; -} - -/* Nav: second level (shown on .active) */ -.bs-sidebar .nav .nav { - display: none; /* Hide by default, but at >768px, show it */ - margin-bottom: 8px; -} -.bs-sidebar .nav .nav > li > a { - padding-top: 3px; - padding-bottom: 3px; - padding-left: 30px; - font-size: 90%; -} - -/* Show and affix the side nav when space allows it */ -@media (min-width: 992px) { - .bs-sidebar .nav > .active > ul { - display: block; - } - /* Widen the fixed sidebar */ - .bs-sidebar.affix, - .bs-sidebar.affix-bottom { - width: 213px; - } - .bs-sidebar.affix { - position: fixed; /* Undo the static from mobile first approach */ - top: 80px; - } - .bs-sidebar.affix-bottom { - position: absolute; /* Undo the static from mobile first approach */ - } - .bs-sidebar.affix-bottom .bs-sidenav, - .bs-sidebar.affix .bs-sidenav { - margin-top: 0; - margin-bottom: 0; - } -} -@media (min-width: 1200px) { - /* Widen the fixed sidebar again */ - .bs-sidebar.affix-bottom, - .bs-sidebar.affix { - width: 263px; - } -} - - -/* - * Docs sections - * - * Content blocks for each component or feature. - */ - -/* Space things out */ -.bs-docs-section + .bs-docs-section { - padding-top: 40px; -} - -/* Janky fix for preventing navbar from overlapping */ -h1[id] { - padding-top: 80px; - margin-top: -45px; -} - - -/* - * Callouts - * - * Not quite alerts, but custom and helpful notes for folks reading the docs. - * Requires a base and modifier class. - */ - -/* Common styles for all types */ -.bs-callout { - margin: 20px 0; - padding: 20px; - border-left: 3px solid #eee; -} -.bs-callout h4 { - margin-top: 0; - margin-bottom: 5px; -} -.bs-callout p:last-child { - margin-bottom: 0; -} - -/* Variations */ -.bs-callout-danger { - background-color: #fdf7f7; - border-color: #eed3d7; -} -.bs-callout-danger h4 { - color: #b94a48; -} -.bs-callout-warning { - background-color: #faf8f0; - border-color: #faebcc; -} -.bs-callout-warning h4 { - color: #8a6d3b; -} -.bs-callout-info { - background-color: #f4f8fa; - border-color: #bce8f1; -} -.bs-callout-info h4 { - color: #34789a; -} - - -/* - * Team members - * - * Avatars, names, and usernames for core team. - */ - -.bs-team .team-member { - color: #555; - line-height: 32px; -} -.bs-team .team-member:hover { - color: #333; - text-decoration: none; -} -.bs-team .github-btn { - float: right; - margin-top: 6px; - width: 120px; - height: 20px; -} -.bs-team img { - float: left; - width: 32px; - margin-right: 10px; - border-radius: 4px; -} - - -/* - * Grid examples - * - * Highlight the grid columns within the docs so folks can see their padding, - * alignment, sizing, etc. - */ - -.show-grid { - margin-bottom: 15px; -} -.show-grid [class^="col-"] { - padding-top: 10px; - padding-bottom: 10px; - background-color: #eee; - border: 1px solid #ddd; - background-color: rgba(86,61,124,.15); - border: 1px solid rgba(86,61,124,.2); -} - - -/* - * Examples - * - * Isolated sections of example content for each component or feature. Usually - * followed by a code snippet. - */ - -.bs-example { - position: relative; - padding: 45px 15px 15px; - margin: 0 -15px 15px; - background-color: #fafafa; - box-shadow: inset 0 3px 6px rgba(0,0,0,.05); - border-color: #e5e5e5 #eee #eee; - border-style: solid; - border-width: 1px 0; -} -/* Echo out a label for the example */ -.bs-example:after { - content: "Example"; - position: absolute; - top: 15px; - left: 15px; - font-size: 12px; - font-weight: bold; - color: #bbb; - text-transform: uppercase; - letter-spacing: 1px; -} - -/* Tweak display of the code snippets when following an example */ -.bs-example + .highlight { - margin: -15px -15px 15px; - border-radius: 0; - border-width: 0 0 1px; -} - -/* Make the examples and snippets not full-width */ -@media (min-width: 768px) { - .bs-example { - margin-left: 0; - margin-right: 0; - background-color: #fff; - border-width: 1px; - border-color: #ddd; - border-radius: 4px 4px 0 0; - box-shadow: none; - } - .bs-example + .highlight { - margin-top: -16px; - margin-left: 0; - margin-right: 0; - border-width: 1px; - border-bottom-left-radius: 4px; - border-bottom-right-radius: 4px; - } -} - -/* Undo width of container */ -.bs-example .container { - width: auto; -} - -/* Tweak content of examples for optimum awesome */ -.bs-example > p:last-child, -.bs-example > ul:last-child, -.bs-example > ol:last-child, -.bs-example > blockquote:last-child, -.bs-example > .form-control:last-child, -.bs-example > .table:last-child, -.bs-example > .navbar:last-child, -.bs-example > .jumbotron:last-child, -.bs-example > .alert:last-child, -.bs-example > .panel:last-child, -.bs-example > .list-group:last-child, -.bs-example > .well:last-child, -.bs-example > .progress:last-child, -.bs-example > .table-responsive:last-child > .table { - margin-bottom: 0; -} -.bs-example > p > .close { - float: none; -} - -/* Typography */ -.bs-example-type .table .info { - color: #999; - vertical-align: middle; -} -.bs-example-type .table td { - padding: 15px 0; - border-color: #eee; -} -.bs-example-type .table tr:first-child td { - border-top: 0; -} -.bs-example-type h1, -.bs-example-type h2, -.bs-example-type h3, -.bs-example-type h4, -.bs-example-type h5, -.bs-example-type h6 { - margin: 0; -} - -/* Images */ -.bs-example > .img-circle, -.bs-example > .img-rounded, -.bs-example > .img-thumbnail { - margin: 5px; -} - -/* Tables */ -.bs-example > .table-responsive > .table { - background-color: #fff; -} - -/* Buttons */ -.bs-example > .btn, -.bs-example > .btn-group { - margin-top: 5px; - margin-bottom: 5px; -} -.bs-example > .btn-toolbar + .btn-toolbar { - margin-top: 10px; -} - -/* Forms */ -.bs-example-control-sizing select, -.bs-example-control-sizing input[type="text"] + input[type="text"] { - margin-top: 10px; -} -.bs-example-form .input-group { - margin-bottom: 10px; -} -.bs-example > textarea.form-control { - resize: vertical; -} - -/* List groups */ -.bs-example > .list-group { - max-width: 400px; -} - -/* Navbars */ -.bs-example .navbar:last-child { - margin-bottom: 0; -} -.bs-navbar-top-example, -.bs-navbar-bottom-example { - z-index: 1; - padding: 0; - overflow: hidden; /* cut the drop shadows off */ -} -.bs-navbar-top-example .navbar-header, -.bs-navbar-bottom-example .navbar-header { - margin-left: 0; -} -.bs-navbar-top-example .navbar-fixed-top, -.bs-navbar-bottom-example .navbar-fixed-bottom { - position: relative; - margin-left: 0; - margin-right: 0; -} -.bs-navbar-top-example { - padding-bottom: 45px; -} -.bs-navbar-top-example:after { - top: auto; - bottom: 15px; -} -.bs-navbar-top-example .navbar-fixed-top { - top: -1px; -} -.bs-navbar-bottom-example { - padding-top: 45px; -} -.bs-navbar-bottom-example .navbar-fixed-bottom { - bottom: -1px; -} -.bs-navbar-bottom-example .navbar { - margin-bottom: 0; -} -@media (min-width: 768px) { - .bs-navbar-top-example .navbar-fixed-top, - .bs-navbar-bottom-example .navbar-fixed-bottom { - position: absolute; - } - .bs-navbar-top-example { - border-radius: 0 0 4px 4px; - } - .bs-navbar-bottom-example { - border-radius: 4px 4px 0 0; - } -} - -/* Pagination */ -.bs-example .pagination { - margin-top: 10px; - margin-bottom: 10px; -} - -/* Pager */ -.bs-example > .pager { - margin-top: 0; -} - -/* Example modals */ -.bs-example-modal { - background-color: #f5f5f5; -} -.bs-example-modal .modal { - position: relative; - top: auto; - right: auto; - left: auto; - bottom: auto; - z-index: 1; - display: block; -} -.bs-example-modal .modal-dialog { - left: auto; - margin-left: auto; - margin-right: auto; -} - -/* Example dropdowns */ -.bs-example > .dropdown > .dropdown-menu { - position: static; - display: block; - margin-bottom: 5px; -} - -/* Example tabbable tabs */ -.bs-example-tabs .nav-tabs { - margin-bottom: 15px; -} - -/* Tooltips */ -.bs-example-tooltips { - text-align: center; -} -.bs-example-tooltips > .btn { - margin-top: 5px; - margin-bottom: 5px; -} - -/* Popovers */ -.bs-example-popover { - padding-bottom: 24px; - background-color: #f9f9f9; -} -.bs-example-popover .popover { - position: relative; - display: block; - float: left; - width: 260px; - margin: 20px; -} - -/* Scrollspy demo on fixed height div */ -.scrollspy-example { - position: relative; - height: 200px; - margin-top: 10px; - overflow: auto; -} - - -/* - * Code snippets - * - * Generated via Pygments and Jekyll, these are snippets of HTML, CSS, and JS. - */ - -.highlight { - display: none; /* hidden by default, until >480px */ - padding: 9px 14px; - margin-bottom: 14px; - background-color: #f7f7f9; - border: 1px solid #e1e1e8; - border-radius: 4px; -} -.highlight pre { - padding: 0; - margin-top: 0; - margin-bottom: 0; - background-color: transparent; - border: 0; - white-space: nowrap; -} -.highlight pre code { - font-size: inherit; - color: #333; /* Effectively the base text color */ -} -.highlight pre .lineno { - display: inline-block; - width: 22px; - padding-right: 5px; - margin-right: 10px; - text-align: right; - color: #bebec5; -} - -/* Show code snippets when we have the space */ -@media (min-width: 481px) { - .highlight { - display: block; - } -} - - -/* - * Responsive tests - * - * Generate a set of tests to show the responsive utilities in action. - */ - -/* Responsive (scrollable) doc tables */ -.table-responsive .highlight pre { - white-space: normal; -} - -/* Utility classes table */ -.bs-table th small, -.responsive-utilities th small { - display: block; - font-weight: normal; - color: #999; -} -.responsive-utilities tbody th { - font-weight: normal; -} -.responsive-utilities td { - text-align: center; -} -.responsive-utilities td.is-visible { - color: #468847; - background-color: #dff0d8 !important; -} -.responsive-utilities td.is-hidden { - color: #ccc; - background-color: #f9f9f9 !important; -} - -/* Responsive tests */ -.responsive-utilities-test { - margin-top: 5px; -} -.responsive-utilities-test .col-xs-6 { - margin-bottom: 10px; -} -.responsive-utilities-test span { - padding: 15px 10px; - font-size: 14px; - font-weight: bold; - line-height: 1.1; - text-align: center; - border-radius: 4px; -} -.visible-on .col-xs-6 .hidden-xs, -.visible-on .col-xs-6 .hidden-sm, -.visible-on .col-xs-6 .hidden-md, -.visible-on .col-xs-6 .hidden-lg, -.hidden-on .col-xs-6 .hidden-xs, -.hidden-on .col-xs-6 .hidden-sm, -.hidden-on .col-xs-6 .hidden-md, -.hidden-on .col-xs-6 .hidden-lg { - color: #999; - border: 1px solid #ddd; -} -.visible-on .col-xs-6 .visible-xs, -.visible-on .col-xs-6 .visible-sm, -.visible-on .col-xs-6 .visible-md, -.visible-on .col-xs-6 .visible-lg, -.hidden-on .col-xs-6 .visible-xs, -.hidden-on .col-xs-6 .visible-sm, -.hidden-on .col-xs-6 .visible-md, -.hidden-on .col-xs-6 .visible-lg { - color: #468847; - background-color: #dff0d8; - border: 1px solid #d6e9c6; -} - - -/* - * Glyphicons - * - * Special styles for displaying the icons and their classes in the docs. - */ - -.bs-glyphicons { - padding-left: 0; - padding-bottom: 1px; - margin-bottom: 20px; - list-style: none; - overflow: hidden; -} -.bs-glyphicons li { - float: left; - width: 25%; - height: 115px; - padding: 10px; - margin: 0 -1px -1px 0; - font-size: 12px; - line-height: 1.4; - text-align: center; - border: 1px solid #ddd; -} -.bs-glyphicons .glyphicon { - margin-top: 5px; - margin-bottom: 10px; - font-size: 24px; -} -.bs-glyphicons .glyphicon-class { - display: block; - text-align: center; - word-wrap: break-word; /* Help out IE10+ with class names */ -} -.bs-glyphicons li:hover { - background-color: rgba(86,61,124,.1); -} - -@media (min-width: 768px) { - .bs-glyphicons li { - width: 12.5%; - } -} - - -/* - * Customizer - * - * Since this is so form control heavy, we have quite a few styles to customize - * the display of inputs, headings, and more. Also included are all the download - * buttons and actions. - */ - -.bs-customizer .toggle { - float: right; - margin-top: 85px; /* On account of ghetto navbar fix */ -} - -/* Headings and form contrls */ -.bs-customizer label { - margin-top: 10px; - font-weight: 500; - color: #555; -} -.bs-customizer h2 { - margin-top: 0; - margin-bottom: 5px; - padding-top: 30px; -} -.bs-customizer h3 { - margin-bottom: 0; -} -.bs-customizer h4 { - margin-top: 15px; - margin-bottom: 0; -} -.bs-customizer .bs-callout h4 { - margin-top: 0; /* lame, but due to specificity we have to duplicate */ - margin-bottom: 5px; -} -.bs-customizer input[type="text"] { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - background-color: #fafafa; -} -.bs-customizer .help-block { - font-size: 12px; - margin-bottom: 5px; -} - -/* For the variables, use regular weight */ -#less-section label { - font-weight: normal; -} - -/* Downloads */ -.bs-customize-download .btn-outline { - padding: 20px; -} - -/* Error handling */ -.bs-customizer-alert { - position: fixed; - top: 51px; - left: 0; - right: 0; - z-index: 1030; - padding: 15px 0; - color: #fff; - background-color: #d9534f; - box-shadow: inset 0 1px 0 rgba(255,255,255,.25); - border-bottom: 1px solid #b94441; -} -.bs-customizer-alert .close { - margin-top: -4px; - font-size: 24px; -} -.bs-customizer-alert p { - margin-bottom: 0; -} -.bs-customizer-alert .glyphicon { - margin-right: 5px; -} -.bs-customizer-alert pre { - margin: 10px 0 0; - color: #fff; - background-color: #a83c3a; - border-color: #973634; - box-shadow: inset 0 2px 4px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1); -} - - -/* - * Miscellaneous - * - * Odds and ends for optimum docs display. - */ - - /* About page */ - .bs-about { - font-size: 16px; - } - -/* Examples gallery: space out content better */ -.bs-examples h4 { - margin-bottom: 5px; -} -.bs-examples p { - margin-bottom: 20px; -} - -/* Pseudo :focus state for showing how it looks in the docs */ -#focusedInput { - border-color: rgba(82,168,236,.8); - outline: 0; - outline: thin dotted \9; /* IE6-9 */ - -moz-box-shadow: 0 0 8px rgba(82,168,236,.6); - box-shadow: 0 0 8px rgba(82,168,236,.6); -} - -/* Better spacing on download options in getting started */ -.bs-docs-dl-options h4 { - margin-top: 15px; - margin-bottom: 5px; -} - - diff --git a/webroot/AutoSa/static/css/main.css b/webroot/AutoSa/static/css/main.css deleted file mode 100644 index d96dcc01b76c..000000000000 --- a/webroot/AutoSa/static/css/main.css +++ /dev/null @@ -1,133 +0,0 @@ -/*! - * Bootstrap v3.0.3 (http://getbootstrap.com) - * Copyright 2013 Twitter, Inc. - * Licensed under http://www.apache.org/licenses/LICENSE-2.0 - */ - -/*设置全局字体*/ -body,button, input, p, select, textarea,h1 ,h2, h3, h4, h5, h6 { - font-family: "Helvetica Neue", Helvetica, STheiti, "微软雅黑", "宋体", Arial, Tahoma, sans-serif, serif;} - -/*左侧下拉菜单样式*/ - -/*左侧菜单*/ -.sidebar-menu { - border-right: 1px solid #c4c8cb; -} -/*一级菜单*/ -.menu-first { - height: 45px; - line-height: 45px; - background-color: #e9e9e9; - border-top: 1px solid #efefef; - border-bottom: 1px solid #e1e1e1; - padding: 0; - font-size: 14px; - font-weight: normal; - text-align: center; -} -/*一级菜单鼠标划过状态*/ -.menu-first:hover { - text-decoration: none; - background-color: #d6d4d5; - border-top: 1px solid #b7b7b7; - border-bottom: 1px solid #acacac; -} -/*二级菜单*/ -.menu-second li a { - background-color: #f6f6f6; - height: 31px; - line-height: 31px; - border-top: 1px solid #efefef; - border-bottom: 1px solid #efefef; - font-size: 12px; - text-align: center; -} -/*二级菜单鼠标划过样式*/ -.menu-second li a:hover { - text-decoration: none; - background-color: #66c3ec; - border-top: 1px solid #83ceed; - border-bottom: 1px solid #83ceed; - border-right: 3px solid #f8881c; - border-left: 3px solid #66c3ec; -} -/*二级菜单选中状态*/ -.menu-second-selected { - background-color: #66c3ec; - height: 31px; - line-height: 31px; - border-top: 1px solid #83ceed; - border-bottom: 1px solid #83ceed; - border-right: 3px solid #f8881c; - border-left: 3px solid #66c3ec; - text-align: center; -} - -/*覆盖bootstrap的样式*/ - .nav-list,.nav-list li a{ - padding: 0px; - margin: 0px; - } - -/*覆盖bootstrap的样式-大屏幕*/ -.screen { - padding: 10px; - margin-bottom: 10px; - font-size: 12px; - font-weight: 200; - line-height: 2.1428571435; - color: inherit; - background-color: #eeeeee; -} - -.jumbotron h1, -.jumbotron .h1 { - line-height: 1; - color: inherit; -} - -.jumbotron p { - line-height: 1.4; -} - -.container .jumbotron { - border-radius: 6px; -} - -.jumbotron .container { - max-width: 100%; -} - -@media screen and (min-width: 768px) { - .jumbotron { - padding-top: 48px; - padding-bottom: 48px; - } - .container .jumbotron { - padding-right: 60px; - padding-left: 60px; - } - .jumbotron h1, - .jumbotron .h1 { - font-size: 63px; - } -} - -.control-label { - text-align: left !important; -} - -.session_btn { - margin-right: 40px !important; - margin-top: 7px; -} - -select.add-perm { - height: 300px !important; -} - -/*li.dropdown-logout, ul.dropdown-logout { - min-width: 20px !important; - margin-right: 15px; -}*/ \ No newline at end of file diff --git a/webroot/AutoSa/static/fonts/glyphicons-halflings-regular.eot b/webroot/AutoSa/static/fonts/glyphicons-halflings-regular.eot deleted file mode 100644 index 423bd5d3a20b..000000000000 Binary files a/webroot/AutoSa/static/fonts/glyphicons-halflings-regular.eot and /dev/null differ diff --git a/webroot/AutoSa/static/fonts/glyphicons-halflings-regular.woff b/webroot/AutoSa/static/fonts/glyphicons-halflings-regular.woff deleted file mode 100644 index d83c539b8266..000000000000 Binary files a/webroot/AutoSa/static/fonts/glyphicons-halflings-regular.woff and /dev/null differ diff --git a/webroot/AutoSa/static/images/1234.png b/webroot/AutoSa/static/images/1234.png deleted file mode 100644 index 49b594d2a5fa..000000000000 Binary files a/webroot/AutoSa/static/images/1234.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/b.png b/webroot/AutoSa/static/images/b.png deleted file mode 100644 index f184e6269b34..000000000000 Binary files a/webroot/AutoSa/static/images/b.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/bg-body.gif b/webroot/AutoSa/static/images/bg-body.gif deleted file mode 100644 index 5ca214550d1e..000000000000 Binary files a/webroot/AutoSa/static/images/bg-body.gif and /dev/null differ diff --git a/webroot/AutoSa/static/images/bg-button-green.gif b/webroot/AutoSa/static/images/bg-button-green.gif deleted file mode 100644 index c58a9bcc41a7..000000000000 Binary files a/webroot/AutoSa/static/images/bg-button-green.gif and /dev/null differ diff --git a/webroot/AutoSa/static/images/bg-content-box.gif b/webroot/AutoSa/static/images/bg-content-box.gif deleted file mode 100644 index 613162b4e5b5..000000000000 Binary files a/webroot/AutoSa/static/images/bg-content-box.gif and /dev/null differ diff --git a/webroot/AutoSa/static/images/bg-form-field.gif b/webroot/AutoSa/static/images/bg-form-field.gif deleted file mode 100644 index c304dd930d69..000000000000 Binary files a/webroot/AutoSa/static/images/bg-form-field.gif and /dev/null differ diff --git a/webroot/AutoSa/static/images/bg-login.gif b/webroot/AutoSa/static/images/bg-login.gif deleted file mode 100644 index 39f0df6a119e..000000000000 Binary files a/webroot/AutoSa/static/images/bg-login.gif and /dev/null differ diff --git a/webroot/AutoSa/static/images/bg-login1.gif b/webroot/AutoSa/static/images/bg-login1.gif deleted file mode 100644 index b5aa84af4d03..000000000000 Binary files a/webroot/AutoSa/static/images/bg-login1.gif and /dev/null differ diff --git a/webroot/AutoSa/static/images/bg-menu-item-current.gif b/webroot/AutoSa/static/images/bg-menu-item-current.gif deleted file mode 100644 index f5debe458be3..000000000000 Binary files a/webroot/AutoSa/static/images/bg-menu-item-current.gif and /dev/null differ diff --git a/webroot/AutoSa/static/images/bg-menu-item-green.gif b/webroot/AutoSa/static/images/bg-menu-item-green.gif deleted file mode 100644 index 6709fa099357..000000000000 Binary files a/webroot/AutoSa/static/images/bg-menu-item-green.gif and /dev/null differ diff --git a/webroot/AutoSa/static/images/bg-radial-gradient.gif b/webroot/AutoSa/static/images/bg-radial-gradient.gif deleted file mode 100644 index b30cd8a02c60..000000000000 Binary files a/webroot/AutoSa/static/images/bg-radial-gradient.gif and /dev/null differ diff --git a/webroot/AutoSa/static/images/bg-sidebar.gif b/webroot/AutoSa/static/images/bg-sidebar.gif deleted file mode 100644 index d97e978b5f33..000000000000 Binary files a/webroot/AutoSa/static/images/bg-sidebar.gif and /dev/null differ diff --git a/webroot/AutoSa/static/images/bl.png b/webroot/AutoSa/static/images/bl.png deleted file mode 100644 index f6271859d516..000000000000 Binary files a/webroot/AutoSa/static/images/bl.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/br.png b/webroot/AutoSa/static/images/br.png deleted file mode 100644 index 31f204fc451c..000000000000 Binary files a/webroot/AutoSa/static/images/br.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/error.png b/webroot/AutoSa/static/images/error.png deleted file mode 100644 index d4507c0712c2..000000000000 Binary files a/webroot/AutoSa/static/images/error.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/favicon.ico b/webroot/AutoSa/static/images/favicon.ico deleted file mode 100644 index 9d6f63253863..000000000000 Binary files a/webroot/AutoSa/static/images/favicon.ico and /dev/null differ diff --git a/webroot/AutoSa/static/images/hammer.png b/webroot/AutoSa/static/images/hammer.png deleted file mode 100644 index 3dd1d5c59043..000000000000 Binary files a/webroot/AutoSa/static/images/hammer.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/icons/bullet_black.png b/webroot/AutoSa/static/images/icons/bullet_black.png deleted file mode 100644 index 57619706d10d..000000000000 Binary files a/webroot/AutoSa/static/images/icons/bullet_black.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/icons/clock_48.png b/webroot/AutoSa/static/images/icons/clock_48.png deleted file mode 100644 index 9f35bce70db8..000000000000 Binary files a/webroot/AutoSa/static/images/icons/clock_48.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/icons/comment_48.png b/webroot/AutoSa/static/images/icons/comment_48.png deleted file mode 100644 index 69c57b2dc690..000000000000 Binary files a/webroot/AutoSa/static/images/icons/comment_48.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/icons/cross.png b/webroot/AutoSa/static/images/icons/cross.png deleted file mode 100644 index 62c181d4b03e..000000000000 Binary files a/webroot/AutoSa/static/images/icons/cross.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/icons/cross_circle.png b/webroot/AutoSa/static/images/icons/cross_circle.png deleted file mode 100644 index d4507c0712c2..000000000000 Binary files a/webroot/AutoSa/static/images/icons/cross_circle.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/icons/exclamation.png b/webroot/AutoSa/static/images/icons/exclamation.png deleted file mode 100644 index 056f680ad288..000000000000 Binary files a/webroot/AutoSa/static/images/icons/exclamation.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/icons/hammer_screwdriver.png b/webroot/AutoSa/static/images/icons/hammer_screwdriver.png deleted file mode 100644 index 485fcf20b83e..000000000000 Binary files a/webroot/AutoSa/static/images/icons/hammer_screwdriver.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/icons/image_add_48.png b/webroot/AutoSa/static/images/icons/image_add_48.png deleted file mode 100644 index d022e8fb5a94..000000000000 Binary files a/webroot/AutoSa/static/images/icons/image_add_48.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/icons/information.png b/webroot/AutoSa/static/images/icons/information.png deleted file mode 100644 index d39b18dd117e..000000000000 Binary files a/webroot/AutoSa/static/images/icons/information.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/icons/jquery.wysiwyg.gif b/webroot/AutoSa/static/images/icons/jquery.wysiwyg.gif deleted file mode 100644 index fd64e3667187..000000000000 Binary files a/webroot/AutoSa/static/images/icons/jquery.wysiwyg.gif and /dev/null differ diff --git a/webroot/AutoSa/static/images/icons/paper_content_pencil_48.png b/webroot/AutoSa/static/images/icons/paper_content_pencil_48.png deleted file mode 100644 index 1c5d322a3a00..000000000000 Binary files a/webroot/AutoSa/static/images/icons/paper_content_pencil_48.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/icons/pencil.png b/webroot/AutoSa/static/images/icons/pencil.png deleted file mode 100644 index 69b9ccaee4c1..000000000000 Binary files a/webroot/AutoSa/static/images/icons/pencil.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/icons/pencil_48.png b/webroot/AutoSa/static/images/icons/pencil_48.png deleted file mode 100644 index 5473e178d66c..000000000000 Binary files a/webroot/AutoSa/static/images/icons/pencil_48.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/icons/tick_circle.png b/webroot/AutoSa/static/images/icons/tick_circle.png deleted file mode 100644 index de8f000d3bdb..000000000000 Binary files a/webroot/AutoSa/static/images/icons/tick_circle.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/logo.png b/webroot/AutoSa/static/images/logo.png deleted file mode 100644 index a0d0725c8171..000000000000 Binary files a/webroot/AutoSa/static/images/logo.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/logo1.png b/webroot/AutoSa/static/images/logo1.png deleted file mode 100644 index 6c7eb731c9b9..000000000000 Binary files a/webroot/AutoSa/static/images/logo1.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/logo13.png b/webroot/AutoSa/static/images/logo13.png deleted file mode 100644 index 027961b674a8..000000000000 Binary files a/webroot/AutoSa/static/images/logo13.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/menu-current-arrow.gif b/webroot/AutoSa/static/images/menu-current-arrow.gif deleted file mode 100644 index 079ed590e0e3..000000000000 Binary files a/webroot/AutoSa/static/images/menu-current-arrow.gif and /dev/null differ diff --git a/webroot/AutoSa/static/images/new_line.png b/webroot/AutoSa/static/images/new_line.png deleted file mode 100644 index bd62d364aa0d..000000000000 Binary files a/webroot/AutoSa/static/images/new_line.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/nut.png b/webroot/AutoSa/static/images/nut.png deleted file mode 100644 index 1ed4d2f044f5..000000000000 Binary files a/webroot/AutoSa/static/images/nut.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/ok.png b/webroot/AutoSa/static/images/ok.png deleted file mode 100644 index de8f000d3bdb..000000000000 Binary files a/webroot/AutoSa/static/images/ok.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/shortcut-button-bg.gif b/webroot/AutoSa/static/images/shortcut-button-bg.gif deleted file mode 100644 index 48e77b9dbb25..000000000000 Binary files a/webroot/AutoSa/static/images/shortcut-button-bg.gif and /dev/null differ diff --git a/webroot/AutoSa/static/images/tl.png b/webroot/AutoSa/static/images/tl.png deleted file mode 100644 index d99c8f6c6eaa..000000000000 Binary files a/webroot/AutoSa/static/images/tl.png and /dev/null differ diff --git a/webroot/AutoSa/static/images/tr.png b/webroot/AutoSa/static/images/tr.png deleted file mode 100644 index e99b6ec8310e..000000000000 Binary files a/webroot/AutoSa/static/images/tr.png and /dev/null differ diff --git a/webroot/AutoSa/static/js/bootstrap.js b/webroot/AutoSa/static/js/bootstrap.js deleted file mode 100644 index 850e6e53b4b1..000000000000 --- a/webroot/AutoSa/static/js/bootstrap.js +++ /dev/null @@ -1,2006 +0,0 @@ -/*! - * Bootstrap v3.0.3 (http://getbootstrap.com) - * Copyright 2013 Twitter, Inc. - * Licensed under http://www.apache.org/licenses/LICENSE-2.0 - */ - -if (typeof jQuery === "undefined") { throw new Error("Bootstrap requires jQuery") } - -/* ======================================================================== - * Bootstrap: transition.js v3.0.3 - * http://getbootstrap.com/javascript/#transitions - * ======================================================================== - * Copyright 2013 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ======================================================================== */ - - -+function ($) { "use strict"; - - // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) - // ============================================================ - - function transitionEnd() { - var el = document.createElement('bootstrap') - - var transEndEventNames = { - 'WebkitTransition' : 'webkitTransitionEnd' - , 'MozTransition' : 'transitionend' - , 'OTransition' : 'oTransitionEnd otransitionend' - , 'transition' : 'transitionend' - } - - for (var name in transEndEventNames) { - if (el.style[name] !== undefined) { - return { end: transEndEventNames[name] } - } - } - } - - // http://blog.alexmaccaw.com/css-transitions - $.fn.emulateTransitionEnd = function (duration) { - var called = false, $el = this - $(this).one($.support.transition.end, function () { called = true }) - var callback = function () { if (!called) $($el).trigger($.support.transition.end) } - setTimeout(callback, duration) - return this - } - - $(function () { - $.support.transition = transitionEnd() - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: alert.js v3.0.3 - * http://getbootstrap.com/javascript/#alerts - * ======================================================================== - * Copyright 2013 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ======================================================================== */ - - -+function ($) { "use strict"; - - // ALERT CLASS DEFINITION - // ====================== - - var dismiss = '[data-dismiss="alert"]' - var Alert = function (el) { - $(el).on('click', dismiss, this.close) - } - - Alert.prototype.close = function (e) { - var $this = $(this) - var selector = $this.attr('data-target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 - } - - var $parent = $(selector) - - if (e) e.preventDefault() - - if (!$parent.length) { - $parent = $this.hasClass('alert') ? $this : $this.parent() - } - - $parent.trigger(e = $.Event('close.bs.alert')) - - if (e.isDefaultPrevented()) return - - $parent.removeClass('in') - - function removeElement() { - $parent.trigger('closed.bs.alert').remove() - } - - $.support.transition && $parent.hasClass('fade') ? - $parent - .one($.support.transition.end, removeElement) - .emulateTransitionEnd(150) : - removeElement() - } - - - // ALERT PLUGIN DEFINITION - // ======================= - - var old = $.fn.alert - - $.fn.alert = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.alert') - - if (!data) $this.data('bs.alert', (data = new Alert(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - $.fn.alert.Constructor = Alert - - - // ALERT NO CONFLICT - // ================= - - $.fn.alert.noConflict = function () { - $.fn.alert = old - return this - } - - - // ALERT DATA-API - // ============== - - $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: button.js v3.0.3 - * http://getbootstrap.com/javascript/#buttons - * ======================================================================== - * Copyright 2013 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ======================================================================== */ - - -+function ($) { "use strict"; - - // BUTTON PUBLIC CLASS DEFINITION - // ============================== - - var Button = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Button.DEFAULTS, options) - } - - Button.DEFAULTS = { - loadingText: 'loading...' - } - - Button.prototype.setState = function (state) { - var d = 'disabled' - var $el = this.$element - var val = $el.is('input') ? 'val' : 'html' - var data = $el.data() - - state = state + 'Text' - - if (!data.resetText) $el.data('resetText', $el[val]()) - - $el[val](data[state] || this.options[state]) - - // push to event loop to allow forms to submit - setTimeout(function () { - state == 'loadingText' ? - $el.addClass(d).attr(d, d) : - $el.removeClass(d).removeAttr(d); - }, 0) - } - - Button.prototype.toggle = function () { - var $parent = this.$element.closest('[data-toggle="buttons"]') - var changed = true - - if ($parent.length) { - var $input = this.$element.find('input') - if ($input.prop('type') === 'radio') { - // see if clicking on current one - if ($input.prop('checked') && this.$element.hasClass('active')) - changed = false - else - $parent.find('.active').removeClass('active') - } - if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change') - } - - if (changed) this.$element.toggleClass('active') - } - - - // BUTTON PLUGIN DEFINITION - // ======================== - - var old = $.fn.button - - $.fn.button = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.button') - var options = typeof option == 'object' && option - - if (!data) $this.data('bs.button', (data = new Button(this, options))) - - if (option == 'toggle') data.toggle() - else if (option) data.setState(option) - }) - } - - $.fn.button.Constructor = Button - - - // BUTTON NO CONFLICT - // ================== - - $.fn.button.noConflict = function () { - $.fn.button = old - return this - } - - - // BUTTON DATA-API - // =============== - - $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) { - var $btn = $(e.target) - if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') - $btn.button('toggle') - e.preventDefault() - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: carousel.js v3.0.3 - * http://getbootstrap.com/javascript/#carousel - * ======================================================================== - * Copyright 2013 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ======================================================================== */ - - -+function ($) { "use strict"; - - // CAROUSEL CLASS DEFINITION - // ========================= - - var Carousel = function (element, options) { - this.$element = $(element) - this.$indicators = this.$element.find('.carousel-indicators') - this.options = options - this.paused = - this.sliding = - this.interval = - this.$active = - this.$items = null - - this.options.pause == 'hover' && this.$element - .on('mouseenter', $.proxy(this.pause, this)) - .on('mouseleave', $.proxy(this.cycle, this)) - } - - Carousel.DEFAULTS = { - interval: 5000 - , pause: 'hover' - , wrap: true - } - - Carousel.prototype.cycle = function (e) { - e || (this.paused = false) - - this.interval && clearInterval(this.interval) - - this.options.interval - && !this.paused - && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) - - return this - } - - Carousel.prototype.getActiveIndex = function () { - this.$active = this.$element.find('.item.active') - this.$items = this.$active.parent().children() - - return this.$items.index(this.$active) - } - - Carousel.prototype.to = function (pos) { - var that = this - var activeIndex = this.getActiveIndex() - - if (pos > (this.$items.length - 1) || pos < 0) return - - if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) - if (activeIndex == pos) return this.pause().cycle() - - return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) - } - - Carousel.prototype.pause = function (e) { - e || (this.paused = true) - - if (this.$element.find('.next, .prev').length && $.support.transition.end) { - this.$element.trigger($.support.transition.end) - this.cycle(true) - } - - this.interval = clearInterval(this.interval) - - return this - } - - Carousel.prototype.next = function () { - if (this.sliding) return - return this.slide('next') - } - - Carousel.prototype.prev = function () { - if (this.sliding) return - return this.slide('prev') - } - - Carousel.prototype.slide = function (type, next) { - var $active = this.$element.find('.item.active') - var $next = next || $active[type]() - var isCycling = this.interval - var direction = type == 'next' ? 'left' : 'right' - var fallback = type == 'next' ? 'first' : 'last' - var that = this - - if (!$next.length) { - if (!this.options.wrap) return - $next = this.$element.find('.item')[fallback]() - } - - this.sliding = true - - isCycling && this.pause() - - var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction }) - - if ($next.hasClass('active')) return - - if (this.$indicators.length) { - this.$indicators.find('.active').removeClass('active') - this.$element.one('slid.bs.carousel', function () { - var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) - $nextIndicator && $nextIndicator.addClass('active') - }) - } - - if ($.support.transition && this.$element.hasClass('slide')) { - this.$element.trigger(e) - if (e.isDefaultPrevented()) return - $next.addClass(type) - $next[0].offsetWidth // force reflow - $active.addClass(direction) - $next.addClass(direction) - $active - .one($.support.transition.end, function () { - $next.removeClass([type, direction].join(' ')).addClass('active') - $active.removeClass(['active', direction].join(' ')) - that.sliding = false - setTimeout(function () { that.$element.trigger('slid.bs.carousel') }, 0) - }) - .emulateTransitionEnd(600) - } else { - this.$element.trigger(e) - if (e.isDefaultPrevented()) return - $active.removeClass('active') - $next.addClass('active') - this.sliding = false - this.$element.trigger('slid.bs.carousel') - } - - isCycling && this.cycle() - - return this - } - - - // CAROUSEL PLUGIN DEFINITION - // ========================== - - var old = $.fn.carousel - - $.fn.carousel = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.carousel') - var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) - var action = typeof option == 'string' ? option : options.slide - - if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) - if (typeof option == 'number') data.to(option) - else if (action) data[action]() - else if (options.interval) data.pause().cycle() - }) - } - - $.fn.carousel.Constructor = Carousel - - - // CAROUSEL NO CONFLICT - // ==================== - - $.fn.carousel.noConflict = function () { - $.fn.carousel = old - return this - } - - - // CAROUSEL DATA-API - // ================= - - $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { - var $this = $(this), href - var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 - var options = $.extend({}, $target.data(), $this.data()) - var slideIndex = $this.attr('data-slide-to') - if (slideIndex) options.interval = false - - $target.carousel(options) - - if (slideIndex = $this.attr('data-slide-to')) { - $target.data('bs.carousel').to(slideIndex) - } - - e.preventDefault() - }) - - $(window).on('load', function () { - $('[data-ride="carousel"]').each(function () { - var $carousel = $(this) - $carousel.carousel($carousel.data()) - }) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: collapse.js v3.0.3 - * http://getbootstrap.com/javascript/#collapse - * ======================================================================== - * Copyright 2013 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ======================================================================== */ - - -+function ($) { "use strict"; - - // COLLAPSE PUBLIC CLASS DEFINITION - // ================================ - - var Collapse = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Collapse.DEFAULTS, options) - this.transitioning = null - - if (this.options.parent) this.$parent = $(this.options.parent) - if (this.options.toggle) this.toggle() - } - - Collapse.DEFAULTS = { - toggle: true - } - - Collapse.prototype.dimension = function () { - var hasWidth = this.$element.hasClass('width') - return hasWidth ? 'width' : 'height' - } - - Collapse.prototype.show = function () { - if (this.transitioning || this.$element.hasClass('in')) return - - var startEvent = $.Event('show.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - var actives = this.$parent && this.$parent.find('> .panel > .in') - - if (actives && actives.length) { - var hasData = actives.data('bs.collapse') - if (hasData && hasData.transitioning) return - actives.collapse('hide') - hasData || actives.data('bs.collapse', null) - } - - var dimension = this.dimension() - - this.$element - .removeClass('collapse') - .addClass('collapsing') - [dimension](0) - - this.transitioning = 1 - - var complete = function () { - this.$element - .removeClass('collapsing') - .addClass('in') - [dimension]('auto') - this.transitioning = 0 - this.$element.trigger('shown.bs.collapse') - } - - if (!$.support.transition) return complete.call(this) - - var scrollSize = $.camelCase(['scroll', dimension].join('-')) - - this.$element - .one($.support.transition.end, $.proxy(complete, this)) - .emulateTransitionEnd(350) - [dimension](this.$element[0][scrollSize]) - } - - Collapse.prototype.hide = function () { - if (this.transitioning || !this.$element.hasClass('in')) return - - var startEvent = $.Event('hide.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return - - var dimension = this.dimension() - - this.$element - [dimension](this.$element[dimension]()) - [0].offsetHeight - - this.$element - .addClass('collapsing') - .removeClass('collapse') - .removeClass('in') - - this.transitioning = 1 - - var complete = function () { - this.transitioning = 0 - this.$element - .trigger('hidden.bs.collapse') - .removeClass('collapsing') - .addClass('collapse') - } - - if (!$.support.transition) return complete.call(this) - - this.$element - [dimension](0) - .one($.support.transition.end, $.proxy(complete, this)) - .emulateTransitionEnd(350) - } - - Collapse.prototype.toggle = function () { - this[this.$element.hasClass('in') ? 'hide' : 'show']() - } - - - // COLLAPSE PLUGIN DEFINITION - // ========================== - - var old = $.fn.collapse - - $.fn.collapse = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.collapse') - var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) - - if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.collapse.Constructor = Collapse - - - // COLLAPSE NO CONFLICT - // ==================== - - $.fn.collapse.noConflict = function () { - $.fn.collapse = old - return this - } - - - // COLLAPSE DATA-API - // ================= - - $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) { - var $this = $(this), href - var target = $this.attr('data-target') - || e.preventDefault() - || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 - var $target = $(target) - var data = $target.data('bs.collapse') - var option = data ? 'toggle' : $this.data() - var parent = $this.attr('data-parent') - var $parent = parent && $(parent) - - if (!data || !data.transitioning) { - if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed') - $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') - } - - $target.collapse(option) - }) - -}(jQuery); - -/* ======================================================================== - * Bootstrap: dropdown.js v3.0.3 - * http://getbootstrap.com/javascript/#dropdowns - * ======================================================================== - * Copyright 2013 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ======================================================================== */ - - -+function ($) { "use strict"; - - // DROPDOWN CLASS DEFINITION - // ========================= - - var backdrop = '.dropdown-backdrop' - var toggle = '[data-toggle=dropdown]' - var Dropdown = function (element) { - $(element).on('click.bs.dropdown', this.toggle) - } - - Dropdown.prototype.toggle = function (e) { - var $this = $(this) - - if ($this.is('.disabled, :disabled')) return - - var $parent = getParent($this) - var isActive = $parent.hasClass('open') - - clearMenus() - - if (!isActive) { - if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { - // if mobile we use a backdrop because click events don't delegate - $('