├── .github └── workflows │ └── docker_build.yml ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Pipfile ├── Pipfile.lock ├── README.md ├── _config.yml ├── app ├── __init__.py ├── admin.py ├── apps.py ├── forms.py ├── models.py ├── tests.py └── views.py ├── daohang ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py ├── db.sqlite3 ├── doc ├── daohang_v1.png └── daohang_v2.png ├── docker-compose.yml ├── issue_template.md ├── manage.py ├── renovate.json ├── requirements.txt ├── static └── app │ ├── css │ ├── base-7f4c8a3613.css │ ├── iconfont-c146519af4.css │ └── index-4092c51499.css │ ├── fonts │ └── iconfont.ttf?t=1490497072 │ ├── image │ ├── favicon.ico │ └── wechat.jpg │ └── js │ ├── index-cbeda4f642.js │ ├── jquery-feda3bc821.min.js │ └── template-native-e7f003bd4a.js └── templates ├── 404.html ├── base.html ├── commit.html └── index.html /.github/workflows/docker_build.yml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://json.schemastore.org/github-workflow 2 | name: Build Docker Image 3 | 4 | # 当 push 到 master 分支,或者创建以 v 开头的 tag 时触发,可根据需求修改 5 | on: 6 | push: 7 | branches: 8 | - master 9 | tags: 10 | - v* 11 | 12 | env: 13 | REGISTRY: ghcr.io 14 | IMAGE: zhuima/daohang 15 | 16 | jobs: 17 | build-and-push: 18 | runs-on: ubuntu-latest 19 | 20 | # 这里用于定义 GITHUB_TOKEN 的权限 21 | permissions: 22 | packages: write 23 | contents: read 24 | 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v2 28 | 29 | # # 缓存 Docker 镜像以加速构建 30 | # - name: Cache Docker layers 31 | # uses: actions/cache@v2 32 | # with: 33 | # path: /tmp/.buildx-cache 34 | # key: ${{ runner.os }}-buildx-${{ github.sha }} 35 | # restore-keys: | 36 | # ${{ runner.os }}-buildx- 37 | 38 | # 配置 QEMU 和 buildx 用于多架构镜像的构建 39 | - name: Set up QEMU 40 | uses: docker/setup-qemu-action@v1 41 | 42 | - name: Set up Docker Buildx 43 | id: buildx 44 | uses: docker/setup-buildx-action@v1 45 | 46 | - name: Inspect builder 47 | run: | 48 | echo "Name: ${{ steps.buildx.outputs.name }}" 49 | echo "Endpoint: ${{ steps.buildx.outputs.endpoint }}" 50 | echo "Status: ${{ steps.buildx.outputs.status }}" 51 | echo "Flags: ${{ steps.buildx.outputs.flags }}" 52 | echo "Platforms: ${{ steps.buildx.outputs.platforms }}" 53 | 54 | # 登录到 GitHub Packages 容器仓库 55 | # 注意 secrets.GITHUB_TOKEN 不需要手动添加,直接就可以用 56 | - name: Log in to the Container registry 57 | uses: docker/login-action@v1 58 | with: 59 | registry: ${{ env.REGISTRY }} 60 | username: ${{ github.actor }} 61 | password: ${{ secrets.DOCKERBUILD_GITHUB_TOKEN }} 62 | 63 | # 根据输入自动生成 tag 和 label 等数据,说明见下 64 | - name: Extract metadata for Docker 65 | id: meta 66 | uses: docker/metadata-action@v3 67 | with: 68 | images: ${{ env.REGISTRY }}/${{ env.IMAGE }} 69 | 70 | # 构建并上传 71 | - name: Build and push 72 | uses: docker/build-push-action@v2 73 | with: 74 | context: . 75 | file: ./Dockerfile 76 | # target: production 77 | builder: ${{ steps.buildx.outputs.name }} 78 | platforms: linux/amd64,linux/arm64 79 | push: true 80 | tags: ${{ steps.meta.outputs.tags }} 81 | labels: ${{ steps.meta.outputs.labels }} 82 | # cache-from: type=local,src=/tmp/.buildx-cache 83 | # cache-to: type=local,dest=/tmp/.buildx-cache 84 | 85 | - name: Inspect image 86 | run: | 87 | docker buildx imagetools inspect \ 88 | ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ steps.meta.outputs.version }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | *.pid 81 | 82 | # SageMath parsed files 83 | *.sage.py 84 | 85 | # Environments 86 | .flaskenv 87 | .env 88 | .venv 89 | env/ 90 | venv/ 91 | ENV/ 92 | env.bak/ 93 | venv.bak/ 94 | 95 | # Spyder project settings 96 | .spyderproject 97 | .spyproject 98 | 99 | # Rope project settings 100 | .ropeproject 101 | 102 | # mkdocs documentation 103 | /site 104 | 105 | # mypy 106 | .mypy_cache/ 107 | 108 | # Development 109 | *.db 110 | .idea 111 | uploads/* 112 | !uploads/.gitkeep 113 | !uploads/avatars 114 | uploads/avatars/* 115 | !uploads/avatars/.gitkeep 116 | 117 | whooshee 118 | 119 | 120 | # vscode 121 | .vscode -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 更新日志 2 | 3 | ## [0.0.9] - 2020-02-25 4 | 5 | 6 | ### 修改 7 | 8 | * django 从1.8版本升级到2.x版本 9 | 10 | 11 | ### 新增 12 | 13 | 14 | * django-simpleui 模块来渲染后端admin页面 15 | 16 | ### 移除 17 | 18 | * django-suit==0.2.25 模块移除 19 | 20 | 21 | 22 | 23 | ## [0.0.8] - 2019-05-12 24 | 25 | ### 新增 26 | 27 | * 升级到Python3 28 | * 包管理工具更新为pipenv 29 | * 新增自助提交表单功能 30 | * 更新README.md 31 | 32 | 33 | # 更新日志 34 | 35 | ## [0.0.7] - 2018-08-07 36 | 37 | ### 修复 38 | 39 | * 后台登陆url修改singin != signin 40 | * 更新README.md 41 | * 修改Dockerfile中端口和docker-compose.yml中端口为8080 42 | 43 | 44 | # 更新日志 45 | 46 | ## [0.0.6] - 2017-11-11 47 | 48 | ### 更新 49 | 50 | * 更新前端展示主题样式 51 | * 抛弃django模版实现渲染,该用ajax实现 52 | 53 | 54 | ## [0.0.5] - 2017-11-06 55 | 56 | ### 更新 57 | 58 | * 新增贡献者指南相关文档 59 | 60 | 61 | ## [0.0.4] - 2017-10-31 62 | 63 | ### 更新 64 | 65 | * 修复build image的时候pip因为等号两边有空格无法正常安装成功的场景 66 | 67 | 68 | ## [0.0.3] - 2017-10-25 69 | 70 | ### 更新 71 | 72 | * 修复docker-compose.yml中端口映射问题,和Dockerfile中对应的不匹配 73 | 74 | 75 | ## [0.0.2] - 2017-10-25 76 | 77 | ### 新增 78 | 79 | * 支持Docker 80 | * 新增Dockerfile 和docker-compose.yml文件 81 | 82 | 83 | ## [0.0.1] - 2017-10-24 84 | 85 | ### 新增 86 | 87 | * OPS内部使用导航系统, 基于Python + Django实现 88 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # 基本准则 2 | 3 | * **遵循 [接入文档](https://github.com/zhuima/daohang/blob/master/README.md). 4 | * **理解 [项目迭代](https://github.com/zhuima/daohang/blob/master/CHANGELOG.md) 5 | * **在创建新issue前先搜索 [已有的issues](https://github.com/zhuima/daohang/issus).** 在已有的issue上补充你发现的有助于解决问题的新信息. 6 | * **只创建跟daohang框架有关的issue.** 如果问题是“怎么实现...”, 7 | * **保持issue简洁有效.** 提供所有有助于解决问题的系统环境, 不要含混无关的细节. 一个好的issue应该能够让我们更快地解决它而非讨论它. 8 | * **及时跟踪反馈你的issue.** 及时的反馈将有助于我们更快的修复它并且发布到新的版本里. 9 | * **使用 [Markdown语法](https://help.github.com/articles/markdown-basics/).** 把代码块与日志输出放到反引号区间里 (```` ``` ````). 10 | * **不要灌水.** 尽可能多地提供有用的信息,不要简单地 +1. 不要评论无关daohang的issue. 11 | 12 | ## 提bug 13 | 14 | 简而言之, 大家都是开发者, 请提出 _你自己_ _希望收到的_ bug. 15 | 16 | 我们 **不是** 为你的个人项目服务. 我们依赖 _你_ (你的团队) 17 | 的贡献以使得我们的框架更好地服务于大家. 在创建issue前请充分调试并排除自己的bug,并告知你所有尝试过的解决方法跟对应的结果. 18 | 如果无法准确地复现问题,将很难跟进。 19 | 20 | 首先请确认你已经使用了 [最新](https://github.com/zhuima/daohang) 的 `最新版本`. 21 | 或者查看更新日志来确认问题是否已在新版本中解决。 22 | 23 | - [daohang CHANGELOG](https://github.com/zhuima/daohang/blob/master/CHANGELOG.md) 24 | 25 | 26 | 请提供复现问题的步骤以及 _所有_ 其它相关的信息, 27 | 28 | 如果没有按照规范来提问并且没有进一步的跟进,问题将被认定为无效并关闭。 29 | 30 | 如果是编译阶段出现的错误,请贴出 `环境信息` 来描述你碰到的问题。 31 | 32 | 33 | 如果你已经熟悉了Github,在你的fork分支上构造一个引发错误的用例将有助于加快bug的解决。 34 | 35 | ## 提功能需求 36 | 37 | 请尽量精确地给出该功能的预期结果,以及这个功能对现有功能的影响。 38 | 39 | > 根据二八原则,请提出能够正向影响到80%使用者的需求。 40 | 41 | ## 提交代码 42 | 43 | 我们欢迎大家提PR,并将合并有意义的提交。 44 | 更多提交代码的流程与规范,建议先阅读下 [开源贡献指南](https://guides.github.com/activities/contributing-to-open-source)。 45 | 46 | 所有的贡献 _将_ 遵循 Apache 2.0 开源协议. 47 | 48 | ## 规范要求 49 | 50 | 如果你已经认真阅读了本指南并同意本指南,请使用我们的 [模板](https://github.com/zhuima/daohang/blob/master/issue_template.md) 来创建issue。 51 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 基础镜像 2 | FROM python:3.7.2 3 | 4 | # 维护者信息 5 | MAINTAINER zhuima 6 | 7 | # app 所在目录 8 | WORKDIR /usr/local/web 9 | ADD . /usr/local/web/ 10 | 11 | # 安装 app 所需依赖 12 | RUN cd /usr/local/web/ && python -m pip install --no-cache-dir -r requirements.txt -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com 13 | 14 | EXPOSE 8080 15 | CMD python manage.py runserver 0.0.0.0:8080 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | name = "pypi" 3 | url = "https://pypi.org/simple" 4 | verify_ssl = true 5 | 6 | [dev-packages] 7 | autopep8 = "*" 8 | 9 | [packages] 10 | Django = "==4.0.4" 11 | django-suit = "==0.2.20" 12 | django-widget-tweaks = "*" 13 | 14 | [requires] 15 | python_version = "3.5.2" -------------------------------------------------------------------------------- /Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "1d1a3b82ec30da763f6e0ff907df33cff6844bef66383f2387bdb69742557fe5" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3.5.2" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.org/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": { 19 | "django": { 20 | "hashes": [ 21 | "sha256:c6c7e7a961e2847d050d214ca96dc3167bb5f2b25cd5c6cb2eea96e1717f4ade", 22 | "sha256:d92ad85a8684d86d078312acb0860824861a3cfcb482428f40878421f2253398" 23 | ], 24 | "index": "pypi", 25 | "version": "==1.8.1" 26 | }, 27 | "django-suit": { 28 | "hashes": [ 29 | "sha256:06297646caf3321f502369fdadeca92a9aab7e2ff4ffbf8b9cc226d8364a3864" 30 | ], 31 | "index": "pypi", 32 | "version": "==0.2.20" 33 | }, 34 | "django-widget-tweaks": { 35 | "hashes": [ 36 | "sha256:a69cba6c8a6b98f0cf6eef0535f8212d635e19044ee4533d4d78df700c2e233f", 37 | "sha256:bc645ef88307bc4ac269ee8ee9e572be814cd4a125c2bb6edb59ffcdc194982d" 38 | ], 39 | "index": "pypi", 40 | "version": "==1.4.3" 41 | } 42 | }, 43 | "develop": { 44 | "autopep8": { 45 | "hashes": [ 46 | "sha256:33d2b5325b7e1afb4240814fe982eea3a92ebea712869bfd08b3c0393404248c" 47 | ], 48 | "index": "pypi", 49 | "version": "==1.4.3" 50 | }, 51 | "pycodestyle": { 52 | "hashes": [ 53 | "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", 54 | "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" 55 | ], 56 | "version": "==2.5.0" 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | OP内部导航系统 2 | ============ 3 | 4 | [![Python 3.5](https://img.shields.io/badge/python-3.5-yellow.svg)](https://www.python.org/) 5 | [![](https://img.shields.io/badge/django-2.2.4-green.svg)](https://www.djangoproject.com/) 6 | [![](https://img.shields.io/badge/simpleui-3.9-green.svg)](https://newpanjing.github.io/simpleui/) 7 | 8 | 9 | 10 | ### 一、关于daohang 11 | 12 | - 运维内部常用管理工具网址索引页 13 | - 用以统计常用地址 14 | 15 | 16 | 17 | ### 二、具体使用 18 | 19 | ```cpp 20 | 0、git clone https://github.com/zhuima/daohang.git 21 | 1、cd daohang && pipenv install && pipenv shell 22 | 2、python manage.py runserver 0.0.0.0:8080 23 | 3、http://ip:8080 24 | ``` 25 | 26 | ### 三、docker支持 27 | 28 | - 借助github workflow的强大功能,增加了docker自动构建,可以直接`docker pull` 29 | 30 | [狠狠的戳我👉](https://github.com/zhuima/daohang/pkgs/container/daohang) 31 | 32 | 33 | - 或者直接使用本仓库的`docker-compose.yml`文件启动,默认使用latest版本 34 | 35 | `docker-composer up -d` 36 | 37 | 38 | ### 四、TODO 39 | 40 | - [x] vue重写前端展示页面和后台管理页面 41 | - [ ] django的RESTful实现 42 | - [ ] 分离脚本和views 43 | 44 | ### 五、说明 45 | 46 | 为了方便大家预览效果,特定把db.sqlite3也上传到了代码仓库, 47 | 后台登陆地址: http://ip:port/signin 48 | 后台管理账号密码: 49 | admin:zhuima 50 | 51 | 52 | ### 六、效果 53 | 54 | > v1版本 55 | 56 | ![](./doc/daohang_v1.png "V1") 57 | 58 | 59 | > v2版本 60 | 61 | ![](./doc/daohang_v2.png "V2") 62 | 63 | 64 | ### 七、致谢 65 | 66 | [caibaojian站点](http://caibaojian.com/daohang) 67 | 68 | [duanlijie站点](http://duanlijie.com/) 69 | 70 | [simpleui](https://newpanjing.github.io/simpleui/QUICK.html) 71 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect -------------------------------------------------------------------------------- /app/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuima/daohang/dff8334418ae6c6d73830b320c5dcf042dce2d2e/app/__init__.py -------------------------------------------------------------------------------- /app/admin.py: -------------------------------------------------------------------------------- 1 | # coding: utf8 2 | 3 | from django.contrib import admin 4 | from .models import UrlGroup, UrlInfor 5 | from django.utils.html import format_html 6 | 7 | # Register your models here. 8 | 9 | 10 | class UrlGroupModelAdmin(admin.ModelAdmin): 11 | # 显示在管理页面的字段 12 | list_display = ("group_name", "gid", "timestamp") 13 | # 可以修改内容的链接 14 | list_display_links = ("gid",) 15 | # 可以查询的字段,显示搜索框 16 | search_fields = ("group_name",) 17 | # 可直接编辑的字段(但是不能同时可连接可编发来) 18 | list_editable = ("group_name",) 19 | # 定制过滤器 20 | list_filter = ("group_name",) 21 | 22 | list_per_page = 10 23 | 24 | class Meta: 25 | model = UrlGroup 26 | 27 | 28 | 29 | class UrlInforModelAdmin(admin.ModelAdmin): 30 | 31 | # 显示在管理页面的字段 32 | list_display = ( 33 | "url_name", 34 | "url_path", 35 | "url_desc", 36 | "url_group", 37 | "url_status", 38 | "timestamp", 39 | ) 40 | # 可以修改内容的链接 41 | list_display_links = ("url_desc",) 42 | # 可以查询的字段,显示搜索框 43 | search_fields = ("url_name",) 44 | # 可直接编辑的字段(但是不能同时可连接可编发来) 45 | list_editable = ("url_status",) 46 | # 定制过滤器 47 | list_filter = ("url_name",) 48 | 49 | list_per_page = 10 50 | 51 | class Meta: 52 | model = UrlInfor 53 | 54 | 55 | 56 | admin.site.register(UrlGroup, UrlGroupModelAdmin) 57 | admin.site.register(UrlInfor, UrlInforModelAdmin) 58 | -------------------------------------------------------------------------------- /app/apps.py: -------------------------------------------------------------------------------- 1 | 2 | from django.apps import AppConfig 3 | 4 | 5 | class AppConfig(AppConfig): 6 | name = 'app' 7 | verbose_name = "导航管理" -------------------------------------------------------------------------------- /app/forms.py: -------------------------------------------------------------------------------- 1 | # coding: utf8 2 | 3 | from django import forms 4 | from django.conf import settings 5 | 6 | from app.models import UrlInfor 7 | from django.utils.http import is_safe_url 8 | 9 | 10 | class CommitForm(forms.ModelForm): 11 | def __init__(self, *args, **kwargs): 12 | super(CommitForm, self).__init__(*args, **kwargs) 13 | self.fields["url_name"].help_text = "链接名称,例如:wiki." 14 | self.fields["url_path"].help_text = "链接,例如:https://zh.wikipedia.org/zh/Wiki." 15 | self.fields["url_desc"].help_text = "链接描述:,例如:这是wiki链接,你可以通过这个链接了解相关技术。" 16 | 17 | class Meta: 18 | model = UrlInfor 19 | fields = ["url_name", "url_path", "url_group", "url_desc"] 20 | 21 | def clean_url_name(self): 22 | url_name = self.cleaned_data.get("url_name") 23 | exists = UrlInfor.objects.filter(url_name=url_name).exists() 24 | if exists: 25 | raise forms.ValidationError(message="%s 已经存在了" % url_name) 26 | else: 27 | return url_name 28 | 29 | def clean_url_path(self): 30 | url_path = self.cleaned_data.get("url_path") 31 | exists = is_safe_url(url=url_path, allowed_hosts=settings.ALLOWED_HOSTS) 32 | if exists: 33 | raise forms.ValidationError(message="%s url不合法" % url_path) 34 | else: 35 | return url_path 36 | -------------------------------------------------------------------------------- /app/models.py: -------------------------------------------------------------------------------- 1 | # coding: utf8 2 | 3 | from django.db import models 4 | from django.contrib.auth.models import User 5 | from django.utils import timezone as tz 6 | 7 | # Create your models here. 8 | 9 | 10 | class UrlGroup(models.Model): 11 | """ 12 | 定义导航项目的组 13 | """ 14 | 15 | group_name = models.CharField(u"分类名称", max_length=100, unique=True) 16 | gid = models.CharField(u"标签名称", max_length=100) 17 | timestamp = models.DateTimeField(u"创建时间", default=tz.now) 18 | 19 | class Meta: 20 | db_table = "app_urlgroup" 21 | verbose_name = u"导航分组" 22 | verbose_name_plural = u"导航分组" 23 | 24 | def __str__(self): 25 | return self.group_name 26 | 27 | 28 | class UrlInfor(models.Model): 29 | """ 30 | 定义导航项目的具体信息 31 | """ 32 | 33 | url_name = models.CharField(u"链接名称", max_length=100) 34 | url_path = models.CharField(u"链接URL", max_length=200) 35 | url_desc = models.TextField(u"链接描述", max_length=200) 36 | url_status = models.BooleanField(u"状态", default=False) 37 | url_group = models.ForeignKey( 38 | UrlGroup, 39 | verbose_name=u"分类名称", 40 | related_name="group_set", 41 | on_delete=models.CASCADE, 42 | ) 43 | timestamp = models.DateTimeField(u"创建时间", default=tz.now) 44 | 45 | class Meta: 46 | db_table = "app_urlinfor" 47 | verbose_name = u"导航详情" 48 | verbose_name_plural = u"导航详情" 49 | ordering = ["url_name"] 50 | 51 | def __str__(self): 52 | return self.url_name 53 | -------------------------------------------------------------------------------- /app/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /app/views.py: -------------------------------------------------------------------------------- 1 | # coding: utf8 2 | # Create your views here. 3 | 4 | import datetime 5 | import json 6 | 7 | from django.contrib import messages 8 | 9 | # from django.core.urlresolvers import reverse 10 | from django.urls import reverse 11 | from django.http import HttpResponse, HttpResponseRedirect 12 | from django.shortcuts import render 13 | from django.views import generic 14 | 15 | from app.forms import CommitForm 16 | from app.models import UrlGroup, UrlInfor 17 | 18 | 19 | def index(request): 20 | """ 21 | 前端展示文件入口 22 | """ 23 | today = datetime.date.today() 24 | weekday = get_week_day(datetime.datetime.now()) 25 | return render(request, "index.html", {"today": today, "weekday": weekday}) 26 | 27 | 28 | def get_week_day(date): 29 | """ 30 | 获取当天是星期几,用来实现页面展示 31 | """ 32 | week_day_dict = { 33 | 0: "星期一", 34 | 1: "星期二", 35 | 2: "星期三", 36 | 3: "星期四", 37 | 4: "星期五", 38 | 5: "星期六", 39 | 6: "星期天", 40 | } 41 | day = date.weekday() 42 | return week_day_dict[day] 43 | 44 | 45 | def serialization_data(request): 46 | """ 47 | 构造数据格式 48 | list 49 | dict 50 | list 51 | dict 52 | 53 | 从组里取出所有组,然后再根据一对多的关系,通过组获取url的具体信息,属于反向获取数据 54 | http://830909.blog.51cto.com/8311014/1765596 55 | http://www.cnpythoner.com/post/135.html 56 | [{"gid": "production", "list": [{"desc": "\u7ebf\u4e0aelk\u65e5\u5fd7\u68c0\u7d22\u7cfb\u7edf", "href": "http://192.168.0.210", "title": "\u7ebf\u4e0aelk\u7cfb\u7edf"}, {"desc": "\u7ebf\u4e0a\u90ae\u7bb1\u5730\u5740\uff0c\u516c\u53f8\u5185\u90e8\u90ae\u7bb1\u767b\u9646\u94fe\u63a5", "href": "http://192.168.0.215", "title": "\u90ae\u7bb1\u5730\u5740"}], "title": "\u751f\u4ea7\u73af\u5883"}, {"gid": "staging", "list": [{"desc": "zabbix\u76d1\u63a7\u7cfb\u7edf\uff0c\u53ef\u4ee5\u7cfb\u7edf\u7cfb\u7edf\u548c\u5e94\u7528\u5c42\u7684\u76d1\u63a7\u4fe1\u606f", "href": "http://192.168.0.211", "title": "\u7ebf\u4e0azabbix\u7cfb\u7edf"}], "title": "\u9884\u53d1\u73af\u5883"}, {"gid": "testing", "list": [{"desc": "\u8fd0\u7ef4\u5185\u90e8nginx\u7ba1\u7406\u5e73\u53f0", "href": "http://192.168.0.215", "title": "\u7ebf\u4e0anginx\u7ba1\u7406\u5e73\u53f0"}, {"desc": "sdf", "href": "http://192.168.0.212", "title": "\u7ebf\u4e0arundeck"}], "title": "\u6d4b\u8bd5\u73af\u5883"}, {"gid": "loading", "list": [{"desc": "\u538b\u6d4b\u73af\u5883\u4ee3\u7801\u53d1\u5e03\u4e4bjenkins\u4e13\u7528", "href": "http://192.168.0.212", "title": "jenkins"}], "title": "\u538b\u6d4b\u73af\u5883"}, {"gid": "QA", "list": [{"desc": "qa\u4e13\u7528SmokeTest\u9875\u9762", "href": "http://192.168.0.215", "title": "smoketest"}], "title": "QA\u4e13\u573a"}, {"gid": "new_work", "list": [{"desc": "\u4e2a\u4eba\u5f00\u53d1\u673a\u5668\u7533\u8bf7\uff0c\u7528\u4e8e\u4e2a\u4eba\u5199\u4ee3\u7801\u7528\u9014", "href": "http://192.168.0.214", "title": "\u4e2a\u4eba\u5f00\u53d1\u673a\u7533\u8bf7"}, {"desc": "\u7528\u4e8e\u767b\u9646\u7ebf\u4e0b\u3001\u7ebf\u4e0a\u5821\u5792\u673a", "href": "http://192.168.0.215", "title": "\u5821\u5792\u673a\u8d26\u53f7\u7533\u8bf7"}], "title": "\u65b0\u5458\u5de5\u4e0a\u624b"}] 57 | """ 58 | 59 | _group_lists = UrlGroup.objects.all().order_by("timestamp") 60 | _datas = [] 61 | for group in _group_lists.all(): 62 | if group.group_set.count() > 0: 63 | _group_template = { 64 | "title": u"{0}".format(group.group_name), 65 | "gid": u"{0}".format(group.gid), 66 | "list": [], 67 | } 68 | _group = UrlGroup.objects.get(gid=group.gid) 69 | for k in _group.group_set.all(): 70 | if k.url_status: 71 | _url_template = { 72 | "title": u"{0}".format(k.url_name), 73 | "href": "{0}".format(k.url_path), 74 | "desc": u"{0}".format(k.url_desc), 75 | } 76 | _group_template["list"].extend([_url_template]) 77 | _datas.extend([_group_template]) 78 | result = json.dumps(_datas) 79 | return HttpResponse(result) 80 | 81 | 82 | def commit(request): 83 | today = datetime.date.today() 84 | weekday = get_week_day(datetime.datetime.now()) 85 | if request.method == "POST": 86 | form = CommitForm(request.POST) 87 | if form.is_valid(): 88 | urlinfor = form.save(commit=False) 89 | urlinfor.save() 90 | print(urlinfor) 91 | messages.success(request, "提交成功! 审核期1个工作日。") 92 | return HttpResponseRedirect(reverse("commit")) 93 | else: 94 | form = CommitForm() 95 | return render( 96 | request, "commit.html", {"form": form, "today": today, "weekday": weekday} 97 | ) 98 | -------------------------------------------------------------------------------- /daohang/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuima/daohang/dff8334418ae6c6d73830b320c5dcf042dce2d2e/daohang/__init__.py -------------------------------------------------------------------------------- /daohang/settings.py: -------------------------------------------------------------------------------- 1 | # coding: utf8 2 | # from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS as TCP 3 | from django.contrib.messages import constants as message_constants 4 | 5 | """ 6 | Django settings for daohang project. 7 | 8 | Generated by 'django-admin startproject' using Django 1.10.3. 9 | 10 | For more information on this file, see 11 | https://docs.djangoproject.com/en/1.10/topics/settings/ 12 | 13 | For the full list of settings and their values, see 14 | https://docs.djangoproject.com/en/1.10/ref/settings/ 15 | """ 16 | 17 | import os 18 | 19 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 20 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 21 | 22 | 23 | # Quick-start development settings - unsuitable for production 24 | # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/ 25 | 26 | # SECURITY WARNING: keep the secret key used in production secret! 27 | SECRET_KEY = "^ol2c9_7cv(awauraw5z3bong2ya1=gzewue6bez*nzu^iq1nf" 28 | 29 | # SECURITY WARNING: don't run with debug turned on in production! 30 | DEBUG = True 31 | # DEBUG = False 32 | 33 | 34 | ALLOWED_HOSTS = [] 35 | 36 | 37 | # Application definition 38 | 39 | INSTALLED_APPS = [ 40 | # 'suit', 41 | "simpleui", 42 | "django.contrib.admin", 43 | "django.contrib.auth", 44 | "django.contrib.contenttypes", 45 | "django.contrib.sessions", 46 | "django.contrib.messages", 47 | "django.contrib.staticfiles", 48 | "widget_tweaks", 49 | "app.apps.AppConfig", 50 | ] 51 | 52 | MIDDLEWARE = [ 53 | "django.middleware.security.SecurityMiddleware", 54 | "django.contrib.sessions.middleware.SessionMiddleware", 55 | "django.middleware.common.CommonMiddleware", 56 | "django.middleware.csrf.CsrfViewMiddleware", 57 | "django.contrib.auth.middleware.AuthenticationMiddleware", 58 | "django.contrib.messages.middleware.MessageMiddleware", 59 | "django.middleware.clickjacking.XFrameOptionsMiddleware", 60 | ] 61 | 62 | ROOT_URLCONF = "daohang.urls" 63 | 64 | TEMPLATES = [ 65 | { 66 | "BACKEND": "django.template.backends.django.DjangoTemplates", 67 | "DIRS": [os.path.join(BASE_DIR, "templates")], 68 | "APP_DIRS": True, 69 | "OPTIONS": { 70 | "context_processors": [ 71 | "django.template.context_processors.debug", 72 | "django.template.context_processors.request", 73 | "django.contrib.auth.context_processors.auth", 74 | "django.contrib.messages.context_processors.messages", 75 | ], 76 | }, 77 | }, 78 | ] 79 | 80 | WSGI_APPLICATION = "daohang.wsgi.application" 81 | 82 | 83 | # Database 84 | # https://docs.djangoproject.com/en/1.10/ref/settings/#databases 85 | 86 | DATABASES = { 87 | "default": { 88 | "ENGINE": "django.db.backends.sqlite3", 89 | "NAME": os.path.join(BASE_DIR, "db.sqlite3"), 90 | } 91 | } 92 | 93 | 94 | # Password validation 95 | # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators 96 | 97 | AUTH_PASSWORD_VALIDATORS = [ 98 | { 99 | "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", 100 | }, 101 | {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",}, 102 | {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",}, 103 | {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",}, 104 | ] 105 | 106 | 107 | # 首页图标 108 | SIMPLEUI_HOME_ICON = "layui-icon-rate" 109 | 110 | # header 111 | SIMPLEUI_SITE_HEADER = "运维导航平台" 112 | 113 | 114 | SIMPLEUI_HOME_INFO = False 115 | 116 | 117 | # Internationalization 118 | # https://docs.djangoproject.com/en/1.10/topics/i18n/ 119 | 120 | # LANGUAGE_CODE = 'en-us' 121 | 122 | # 支持中文 123 | LANGUAGE_CODE = "zh-Hans" 124 | 125 | 126 | # 时区修改 127 | TIME_ZONE = "Asia/Shanghai" 128 | 129 | USE_I18N = True 130 | 131 | USE_L10N = False 132 | 133 | USE_TZ = True 134 | 135 | 136 | # Static files (CSS, JavaScript, Images) 137 | # https://docs.djangoproject.com/en/1.10/howto/static-files/ 138 | 139 | 140 | STATIC_URL = "/static/" 141 | 142 | # 支持静态文件 143 | 144 | STATICFILES_DIRS = [ 145 | os.path.join(BASE_DIR, "static"), 146 | ] 147 | 148 | 149 | STATICFILES_FINDERS = ( 150 | "django.contrib.staticfiles.finders.FileSystemFinder", 151 | "django.contrib.staticfiles.finders.AppDirectoriesFinder", 152 | ) 153 | 154 | 155 | SIMPLEUI_ICON = { 156 | "导航分组": "fas fa-american-sign-language-interpreting", 157 | # fas fa-american-sign-language-interpreting 158 | "导航详情": "far fa-hand-point-right", 159 | } 160 | 161 | 162 | MESSAGE_TAGS = { 163 | message_constants.SUCCESS: "alert alert-success", 164 | message_constants.ERROR: "alert alert-danger", 165 | } 166 | -------------------------------------------------------------------------------- /daohang/urls.py: -------------------------------------------------------------------------------- 1 | """daohang URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/1.10/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.conf.urls import url, include 14 | 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) 15 | """ 16 | from django.conf.urls import url 17 | from django.contrib import admin 18 | from app import views as app_views 19 | 20 | admin.site.site_title = "daohang" 21 | admin.site.site_header = "运维内部导航平台" 22 | 23 | 24 | urlpatterns = [ 25 | url(r"^signin/", admin.site.urls, name="login"), 26 | url(r"^$", app_views.index, name="index"), 27 | url(r"^datas/$", app_views.serialization_data, name="datas"), 28 | url(r"^commit/$", app_views.commit, name="commit") 29 | # url(r'^commit/$', app_views.CommitView.as_view(), name='commit') 30 | ] 31 | -------------------------------------------------------------------------------- /daohang/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for daohang project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "daohang.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuima/daohang/dff8334418ae6c6d73830b320c5dcf042dce2d2e/db.sqlite3 -------------------------------------------------------------------------------- /doc/daohang_v1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuima/daohang/dff8334418ae6c6d73830b320c5dcf042dce2d2e/doc/daohang_v1.png -------------------------------------------------------------------------------- /doc/daohang_v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuima/daohang/dff8334418ae6c6d73830b320c5dcf042dce2d2e/doc/daohang_v2.png -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | daohang: 4 | image: ghcr.io/zhuima/daohang 5 | container_name: daohang 6 | restart: always 7 | ports: 8 | - 8080:8080 9 | -------------------------------------------------------------------------------- /issue_template.md: -------------------------------------------------------------------------------- 1 | - [x] 我已阅读并理解 **[贡献指南](https://github.com/zhuima/daohang/CONTRIBUTING.md)**,严格遵循其约定。 2 | 3 | # 错误报告 4 | 5 | ## 你做了什么? 6 | 7 | 我修改了后台管理界面 8 | 9 | ## 你期望的结果是什么? 10 | 11 | daohang能够提供更炫酷的页面,可以拿得出手。 12 | 13 | ## 实际结果是什么? 14 | 15 | daohang页面太过于简陋 16 | 17 | ## daohang环境 18 | 19 | ### vm或物理机器 20 | 21 | ### Docker 22 | 23 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "daohang.settings") 7 | try: 8 | from django.core.management import execute_from_command_line 9 | except ImportError: 10 | # The above import may fail for some other reason. Ensure that the 11 | # issue is really that Django is missing to avoid masking other 12 | # exceptions on Python 2. 13 | try: 14 | import django 15 | except ImportError: 16 | raise ImportError( 17 | "Couldn't import Django. Are you sure it's installed and " 18 | "available on your PYTHONPATH environment variable? Did you " 19 | "forget to activate a virtual environment?" 20 | ) 21 | raise 22 | execute_from_command_line(sys.argv) 23 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Django==2.2.28 2 | django-simpleui==2022.4.9 3 | django-widget-tweaks -------------------------------------------------------------------------------- /static/app/css/base-7f4c8a3613.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";body,dd,dl,dt,fieldset,form,h1,h2,h3,h4,h5,h6,html,img,legend,li,ol,p,ul{margin:0;padding:0}button,fieldset,img,input{border:none;padding:0;margin:0;outline-style:none}ol,ul{list-style:none}input{padding-top:0;padding-bottom:0;font-family:SimSun,"宋体"}input,select{vertical-align:middle}input,select,textarea{font-size:12px;margin:0}textarea{resize:none}img{border:0;vertical-align:middle}table{border-collapse:collapse}body{font:14px/1.5 STHeiti,"Microsoft Yahei","Hiragino Sans GB","Heiti SC","WenQuanYi Micro Hei",sans-serif;color:#fff;background-color:#eee}.clearfix:after{content:"";height:0;line-height:0;display:block;clear:both;visibility:hidden}.clearfix{zoom:1}a{color:#09f;text-decoration:none}a:hover{color:#ff6700}h1,h2,h3,h4,h5,h6{text-decoration:none;font-weight:400;font-size:100%}em,i,s{font-style:normal;text-decoration:none}.wrapper{width:90%;margin:0 auto}@media screen and (max-width:1200px){.wrapper{width:95%}}.fl{float:left}.fr{float:right}.hide{display:none} -------------------------------------------------------------------------------- /static/app/css/iconfont-c146519af4.css: -------------------------------------------------------------------------------- 1 | @font-face{font-family:iconfont;src:url(../fonts/iconfont.eot?t=1490497072);src:url(../fonts/iconfont.eot?t=1490497072#iefix) format("embedded-opentype"),url(../fonts/iconfont.ttf%3Ft=1490497072?t=1490497072) format("woff"),url(../fonts/iconfont.ttf?t=1490497072) format("truetype"),url(../fonts/iconfont.svg?t=1490497072#iconfont) format("svg")}.iconfont{font-family:iconfont!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-webkit-text-stroke-width:.2px;-moz-osx-font-smoothing:grayscale}.icon-up:before{content:"\e65d"}.icon-search:before{content:"\e651"} -------------------------------------------------------------------------------- /static/app/css/index-4092c51499.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";.header{position:relative;width:100%;height:100px;background-color:#09f}.header .logo{line-height:100px}.header .logo a{color:#fff;font-size:26px}@media screen and (max-width:768px){.header .logo{width:100%;text-align:center}}.header .desc{height:40px;margin-top:30px;line-height:20px;color:#fff;text-align:center}@media screen and (max-width:960px){.header .desc{display:none}}.header .search{position:absolute;bottom:32.5px;right:40%;font-size:0}@media screen and (max-width:960px){.header .search{right:2%}}@media screen and (max-width:768px){.header .search{right:50%;margin-right:-125px;bottom:-50px;z-index:20}}.header .search .search_btn,.header .search .search_txt{display:inline-block;vertical-align:top;height:35px;color:#555}.header .search .search_txt{width:200px;font-size:16px;text-indent:10px;border-radius:2px 0 0 2px;font-family:"Microsoft JhengHei","Microsoft Yahei"}.header .search .search_btn{width:50px;border-radius:0 2px 2px 0;background-color:#0cf;color:#fff}.header .search .search_btn .icon-search{font-size:22px}.container{position:relative}.container .nav{position:absolute;top:0;left:0}@media screen and (max-width:960px){.container .nav{display:none}}.container .nav .nav_item{display:block;width:120px;height:45px;line-height:50px;border-bottom:1px solid #ccc;background-color:#09f;color:#fff;text-align:center;font-size:15px}.container .nav .nav_item.active,.container .nav .nav_item:hover{transition:all .25s linear;border-radius:5px;background-color:#06c;font-weight:700}.container .content{padding:20px 0 0 150px}@media screen and (max-width:960px){.container .content{padding-left:2%}}@media screen and (max-width:768px){.container .content{padding-top:40px}}.container .content .content_items{padding-top:20px}.container .content .content_items .title{width:120px;height:40px;margin-bottom:10px;line-height:40px;border-radius:5px;background-color:#09f;text-align:center;font-size:20px}@media screen and (max-width:640px){.container .content .content_items .title{width:98%}}.container .content .content_items .content_item{width:16%;height:60px;padding:10px;margin-right:10px;margin-bottom:10px;box-shadow:2px 2px 5px 2px #bbb;background-color:#fff;border-radius:5px;overflow:hidden}@media screen and (max-width:1200px){.container .content .content_items .content_item{width:21%}}@media screen and (max-width:825px){.container .content .content_items .content_item{width:27%;margin-right:1%}}@media screen and (max-width:640px){.container .content .content_items .content_item{padding:2%;margin:0 1% 10px}}.container .content .content_items .content_item .link{display:inline-block;font-size:15px;margin-bottom:5px}.container .content .content_items .content_item .text{color:#999;font-size:12px}.container .content .content_items .content_item:hover{transition:all .2s linear;-webkit-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}.footer{position:relative;height:150px;margin-top:50px;background-color:#222;text-align:center;font-size:18px}.footer .info{height:50px;line-height:50px;letter-spacing:2px}.footer img{width:100px;height:100px}.back_to_top{position:fixed;bottom:25px;right:25px}.back_to_top a{display:block;width:50px;height:50px;line-height:50px;border-radius:5px;background-color:rgba(0,0,0,.3);color:#fff;text-align:center;font-size:22px}.back_to_top a:hover{transition:all .2s linear;background-color:rgba(0,0,0,.6)} -------------------------------------------------------------------------------- /static/app/fonts/iconfont.ttf?t=1490497072: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuima/daohang/dff8334418ae6c6d73830b320c5dcf042dce2d2e/static/app/fonts/iconfont.ttf?t=1490497072 -------------------------------------------------------------------------------- /static/app/image/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuima/daohang/dff8334418ae6c6d73830b320c5dcf042dce2d2e/static/app/image/favicon.ico -------------------------------------------------------------------------------- /static/app/image/wechat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhuima/daohang/dff8334418ae6c6d73830b320c5dcf042dce2d2e/static/app/image/wechat.jpg -------------------------------------------------------------------------------- /static/app/js/index-cbeda4f642.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | $.ajax({ 3 | url: "/datas/", type: "get", dataType: "json", success: function (t) { 4 | $(".nav").html(template("nav_tpl", {data: t})), $(".content").html(template("content_tpl", {data: t})) 5 | 6 | } 7 | }), $(".nav").on("click", "li a", function () { 8 | return $("html, body").animate({scrollTop: $($(this).attr("href")).offset().top}), !1 9 | }), $(document).scroll(function (t) { 10 | var o = $(".nav").offset().left; 11 | $(document).scrollTop() >= $(".header").height() ? $(".nav").css({ 12 | position: "fixed", 13 | top: 0, 14 | left: o 15 | }) : $(document).scrollTop() < $(".header").height() && $(".nav").css({ 16 | position: "absolute", 17 | top: 0, 18 | left: 0 19 | }), 20 | //console.log($(".content_items h3").first().offset().top), 21 | $(document).scrollTop() >= $(".content_items h3").first().offset().top ? $(".back_to_top").show() : $(".back_to_top").hide() 22 | }), $(".nav").on("click", ".nav_item", function () { 23 | $(this).parent().siblings().children().removeClass("active"), $(this).addClass("active") 24 | }), $(".back_to_top").click(function () { 25 | return $("html, body").animate({scrollTop: 0}), !1 26 | }) 27 | }); -------------------------------------------------------------------------------- /static/app/js/jquery-feda3bc821.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){"use strict";function n(e,t){t=t||te;var n=t.createElement("script");n.text=e,t.head.appendChild(n).parentNode.removeChild(n)}function r(e){var t=!!e&&"length"in e&&e.length,n=he.type(e);return"function"!==n&&!he.isWindow(e)&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}function i(e,t,n){return he.isFunction(t)?he.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?he.grep(e,function(e){return e===t!==n}):"string"!=typeof t?he.grep(e,function(e){return ae.call(t,e)>-1!==n}):Ee.test(t)?he.filter(t,e,n):(t=he.filter(t,e),he.grep(e,function(e){return ae.call(t,e)>-1!==n&&1===e.nodeType}))}function o(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}function a(e){var t={};return he.each(e.match(Ae)||[],function(e,n){t[n]=!0}),t}function s(e){return e}function u(e){throw e}function l(e,t,n){var r;try{e&&he.isFunction(r=e.promise)?r.call(e).done(t).fail(n):e&&he.isFunction(r=e.then)?r.call(e,t,n):t.call(void 0,e)}catch(e){n.call(void 0,e)}}function c(){te.removeEventListener("DOMContentLoaded",c),e.removeEventListener("load",c),he.ready()}function f(){this.expando=he.expando+f.uid++}function p(e){return"true"===e||"false"!==e&&("null"===e?null:e===+e+""?+e:Re.test(e)?JSON.parse(e):e)}function d(e,t,n){var r;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(Me,"-$&").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n=p(n)}catch(e){}Pe.set(e,t,n)}else n=void 0;return n}function h(e,t,n,r){var i,o=1,a=20,s=r?function(){return r.cur()}:function(){return he.css(e,t,"")},u=s(),l=n&&n[3]||(he.cssNumber[t]?"":"px"),c=(he.cssNumber[t]||"px"!==l&&+u)&&We.exec(he.css(e,t));if(c&&c[3]!==l){l=l||c[3],n=n||[],c=+u||1;do o=o||".5",c/=o,he.style(e,t,c+l);while(o!==(o=s()/u)&&1!==o&&--a)}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}function g(e){var t,n=e.ownerDocument,r=e.nodeName,i=ze[r];return i?i:(t=n.body.appendChild(n.createElement(r)),i=he.css(t,"display"),t.parentNode.removeChild(t),"none"===i&&(i="block"),ze[r]=i,i)}function m(e,t){for(var n,r,i=[],o=0,a=e.length;o-1)i&&i.push(o);else if(l=he.contains(o.ownerDocument,o),a=v(f.appendChild(o),"script"),l&&y(a),n)for(c=0;o=a[c++];)Ve.test(o.type||"")&&n.push(o);return f}function b(){return!0}function w(){return!1}function T(){try{return te.activeElement}catch(e){}}function C(e,t,n,r,i,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(s in t)C(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),i===!1)i=w;else if(!i)return e;return 1===o&&(a=i,i=function(e){return he().off(e),a.apply(this,arguments)},i.guid=a.guid||(a.guid=he.guid++)),e.each(function(){he.event.add(this,t,i,r,n)})}function E(e,t){return he.nodeName(e,"table")&&he.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e:e}function k(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function N(e){var t=rt.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function S(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Oe.hasData(e)&&(o=Oe.access(e),a=Oe.set(t,o),l=o.events)){delete a.handle,a.events={};for(i in l)for(n=0,r=l[i].length;n1&&"string"==typeof h&&!pe.checkClone&&nt.test(h))return e.each(function(n){var o=e.eq(n);g&&(t[0]=h.call(this,n,o.html())),j(o,t,r,i)});if(p&&(o=x(t,e[0].ownerDocument,!1,e,i),a=o.firstChild,1===o.childNodes.length&&(o=a),a||i)){for(s=he.map(v(o,"script"),k),u=s.length;f=0&&nC.cacheLength&&delete e[t.shift()],e[n+" "]=r}var t=[];return e}function r(e){return e[W]=!0,e}function i(e){var t=H.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split("|"),r=n.length;r--;)C.attrHandle[n[r]]=t}function a(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function s(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function u(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function l(e){return function(t){return"form"in t?t.parentNode&&t.disabled===!1?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&Ee(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function c(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function f(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function p(){}function d(e){for(var t=0,n=e.length,r="";t1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function m(e,n,r){for(var i=0,o=n.length;i-1&&(r[l]=!(a[l]=f))}}else x=v(x===a?x.splice(h,x.length):x),o?o(null,a,x,u):K.apply(a,x)})}function x(e){for(var t,n,r,i=e.length,o=C.relative[e[0].type],a=o||C.relative[" "],s=o?1:0,u=h(function(e){return e===t},a,!0),l=h(function(e){return ee(t,e)>-1},a,!0),c=[function(e,n,r){var i=!o&&(r||n!==j)||((t=n).nodeType?u(e,n,r):l(e,n,r));return t=null,i}];s1&&g(c),s>1&&d(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(se,"$1"),n,s0,o=e.length>0,a=function(r,a,s,u,l){var c,f,p,d=0,h="0",g=r&&[],m=[],y=j,x=r||o&&C.find.TAG("*",l),b=B+=null==y?1:Math.random()||.1,w=x.length;for(l&&(j=a===H||a||l);h!==w&&null!=(c=x[h]);h++){if(o&&c){for(f=0,a||c.ownerDocument===H||(L(c),s=!O);p=e[f++];)if(p(c,a||H,s)){u.push(c);break}l&&(B=b)}i&&((c=!p&&c)&&d--,r&&g.push(c))}if(d+=h,i&&h!==d){for(f=0;p=n[f++];)p(g,m,a,s);if(r){if(d>0)for(;h--;)g[h]||m[h]||(m[h]=Q.call(u));m=v(m)}K.apply(u,m),l&&!r&&m.length>0&&d+n.length>1&&t.uniqueSort(u)}return l&&(B=b,j=y),g};return i?r(a):a}var w,T,C,E,k,N,S,D,j,A,q,L,H,F,O,P,R,M,I,W="sizzle"+1*new Date,$=e.document,B=0,_=0,z=n(),X=n(),U=n(),V=function(e,t){return e===t&&(q=!0),0},G={}.hasOwnProperty,Y=[],Q=Y.pop,J=Y.push,K=Y.push,Z=Y.slice,ee=function(e,t){for(var n=0,r=e.length;n+~]|"+ne+")"+ne+"*"),ce=new RegExp("="+ne+"*([^\\]'\"]*?)"+ne+"*\\]","g"),fe=new RegExp(oe),pe=new RegExp("^"+re+"$"),de={ID:new RegExp("^#("+re+")"),CLASS:new RegExp("^\\.("+re+")"),TAG:new RegExp("^("+re+"|[*])"),ATTR:new RegExp("^"+ie),PSEUDO:new RegExp("^"+oe),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ne+"*(even|odd|(([+-]|)(\\d*)n|)"+ne+"*(?:([+-]|)"+ne+"*(\\d+)|))"+ne+"*\\)|)","i"),bool:new RegExp("^(?:"+te+")$","i"),needsContext:new RegExp("^"+ne+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ne+"*((?:-\\d)?\\d*)"+ne+"*\\)|)(?=[^-]|$)","i")},he=/^(?:input|select|textarea|button)$/i,ge=/^h\d$/i,me=/^[^{]+\{\s*\[native \w/,ve=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ye=/[+~]/,xe=new RegExp("\\\\([\\da-f]{1,6}"+ne+"?|("+ne+")|.)","ig"),be=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},we=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,Te=function(e,t){return t?"\0"===e?"�":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},Ce=function(){L()},Ee=h(function(e){return e.disabled===!0&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{K.apply(Y=Z.call($.childNodes),$.childNodes),Y[$.childNodes.length].nodeType}catch(e){K={apply:Y.length?function(e,t){J.apply(e,Z.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}T=t.support={},k=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},L=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:$;return r!==H&&9===r.nodeType&&r.documentElement?(H=r,F=H.documentElement,O=!k(H),$!==H&&(n=H.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",Ce,!1):n.attachEvent&&n.attachEvent("onunload",Ce)),T.attributes=i(function(e){return e.className="i",!e.getAttribute("className")}),T.getElementsByTagName=i(function(e){return e.appendChild(H.createComment("")),!e.getElementsByTagName("*").length}),T.getElementsByClassName=me.test(H.getElementsByClassName),T.getById=i(function(e){return F.appendChild(e).id=W,!H.getElementsByName||!H.getElementsByName(W).length}),T.getById?(C.filter.ID=function(e){var t=e.replace(xe,be);return function(e){return e.getAttribute("id")===t}},C.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&O){var n=t.getElementById(e);return n?[n]:[]}}):(C.filter.ID=function(e){var t=e.replace(xe,be);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},C.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&O){var n,r,i,o=t.getElementById(e);if(o){if(n=o.getAttributeNode("id"),n&&n.value===e)return[o];for(i=t.getElementsByName(e),r=0;o=i[r++];)if(n=o.getAttributeNode("id"),n&&n.value===e)return[o]}return[]}}),C.find.TAG=T.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):T.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},C.find.CLASS=T.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&O)return t.getElementsByClassName(e)},R=[],P=[],(T.qsa=me.test(H.querySelectorAll))&&(i(function(e){F.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&P.push("[*^$]="+ne+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||P.push("\\["+ne+"*(?:value|"+te+")"),e.querySelectorAll("[id~="+W+"-]").length||P.push("~="),e.querySelectorAll(":checked").length||P.push(":checked"),e.querySelectorAll("a#"+W+"+*").length||P.push(".#.+[+~]")}),i(function(e){e.innerHTML="";var t=H.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&P.push("name"+ne+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&P.push(":enabled",":disabled"),F.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&P.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),P.push(",.*:")})),(T.matchesSelector=me.test(M=F.matches||F.webkitMatchesSelector||F.mozMatchesSelector||F.oMatchesSelector||F.msMatchesSelector))&&i(function(e){T.disconnectedMatch=M.call(e,"*"),M.call(e,"[s!='']:x"),R.push("!=",oe)}),P=P.length&&new RegExp(P.join("|")),R=R.length&&new RegExp(R.join("|")),t=me.test(F.compareDocumentPosition),I=t||me.test(F.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},V=t?function(e,t){if(e===t)return q=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n?n:(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!T.sortDetached&&t.compareDocumentPosition(e)===n?e===H||e.ownerDocument===$&&I($,e)?-1:t===H||t.ownerDocument===$&&I($,t)?1:A?ee(A,e)-ee(A,t):0:4&n?-1:1)}:function(e,t){if(e===t)return q=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,s=[e],u=[t];if(!i||!o)return e===H?-1:t===H?1:i?-1:o?1:A?ee(A,e)-ee(A,t):0;if(i===o)return a(e,t);for(n=e;n=n.parentNode;)s.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;s[r]===u[r];)r++;return r?a(s[r],u[r]):s[r]===$?-1:u[r]===$?1:0},H):H},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==H&&L(e),n=n.replace(ce,"='$1']"),T.matchesSelector&&O&&!U[n+" "]&&(!R||!R.test(n))&&(!P||!P.test(n)))try{var r=M.call(e,n);if(r||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return t(n,H,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==H&&L(e),I(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==H&&L(e);var n=C.attrHandle[t.toLowerCase()],r=n&&G.call(C.attrHandle,t.toLowerCase())?n(e,t,!O):void 0;return void 0!==r?r:T.attributes||!O?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.escape=function(e){return(e+"").replace(we,Te)},t.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(q=!T.detectDuplicates,A=!T.sortStable&&e.slice(0),e.sort(V),q){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return A=null,e},E=t.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=E(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=E(t);return n},C=t.selectors={cacheLength:50,createPseudo:r,match:de,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(xe,be),e[3]=(e[3]||e[4]||e[5]||"").replace(xe,be),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||t.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return de.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&fe.test(n)&&(t=N(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(xe,be).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=z[e+" "];return t||(t=new RegExp("(^|"+ne+")"+e+"("+ne+"|$)"))&&z(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?"!="===n:!n||(o+="","="===n?o===r:"!="===n?o!==r:"^="===n?r&&0===o.indexOf(r):"*="===n?r&&o.indexOf(r)>-1:"$="===n?r&&o.slice(-r.length)===r:"~="===n?(" "+o.replace(ae," ")+" ").indexOf(r)>-1:"|="===n&&(o===r||o.slice(0,r.length+1)===r+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,f,p,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,v=s&&t.nodeName.toLowerCase(),y=!u&&!s,x=!1;if(m){if(o){for(;g;){for(p=t;p=p[g];)if(s?p.nodeName.toLowerCase()===v:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&y){for(p=m,f=p[W]||(p[W]={}),c=f[p.uniqueID]||(f[p.uniqueID]={}),l=c[e]||[],d=l[0]===B&&l[1],x=d&&l[2],p=d&&m.childNodes[d];p=++d&&p&&p[g]||(x=d=0)||h.pop();)if(1===p.nodeType&&++x&&p===t){c[e]=[B,d,x];break}}else if(y&&(p=t,f=p[W]||(p[W]={}),c=f[p.uniqueID]||(f[p.uniqueID]={}),l=c[e]||[],d=l[0]===B&&l[1],x=d),x===!1)for(;(p=++d&&p&&p[g]||(x=d=0)||h.pop())&&((s?p.nodeName.toLowerCase()!==v:1!==p.nodeType)||!++x||(y&&(f=p[W]||(p[W]={}),c=f[p.uniqueID]||(f[p.uniqueID]={}),c[e]=[B,x]),p!==t)););return x-=i,x===r||x%r===0&&x/r>=0}}},PSEUDO:function(e,n){var i,o=C.pseudos[e]||C.setFilters[e.toLowerCase()]||t.error("unsupported pseudo: "+e);return o[W]?o(n):o.length>1?(i=[e,e,"",n],C.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),a=i.length;a--;)r=ee(e,i[a]),e[r]=!(t[r]=i[a])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=S(e.replace(se,"$1"));return i[W]?r(function(e,t,n,r){for(var o,a=i(e,null,r,[]),s=e.length;s--;)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(xe,be),function(t){return(t.textContent||t.innerText||E(t)).indexOf(e)>-1}}),lang:r(function(e){return pe.test(e||"")||t.error("unsupported lang: "+e),e=e.replace(xe,be).toLowerCase(),function(t){var n;do if(n=O?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1; 2 | }}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===F},focus:function(e){return e===H.activeElement&&(!H.hasFocus||H.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:l(!1),disabled:l(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!C.pseudos.empty(e)},header:function(e){return ge.test(e.nodeName)},input:function(e){return he.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:c(function(){return[0]}),last:c(function(e,t){return[t-1]}),eq:c(function(e,t,n){return[n<0?n+t:n]}),even:c(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:c(function(e,t,n){for(var r=n<0?n+t:n;++r2&&"ID"===(a=o[0]).type&&9===t.nodeType&&O&&C.relative[o[1].type]){if(t=(C.find.ID(a.matches[0].replace(xe,be),t)||[])[0],!t)return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=de.needsContext.test(e)?0:o.length;i--&&(a=o[i],!C.relative[s=a.type]);)if((u=C.find[s])&&(r=u(a.matches[0].replace(xe,be),ye.test(o[0].type)&&f(t.parentNode)||t))){if(o.splice(i,1),e=r.length&&d(o),!e)return K.apply(n,r),n;break}}return(l||S(e,c))(r,t,!O,n,!t||ye.test(e)&&f(t.parentNode)||t),n},T.sortStable=W.split("").sort(V).join("")===W,T.detectDuplicates=!!q,L(),T.sortDetached=i(function(e){return 1&e.compareDocumentPosition(H.createElement("fieldset"))}),i(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||o("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),T.attributes&&i(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||o("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute("disabled")})||o(te,function(e,t,n){var r;if(!n)return e[t]===!0?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);he.find=xe,he.expr=xe.selectors,he.expr[":"]=he.expr.pseudos,he.uniqueSort=he.unique=xe.uniqueSort,he.text=xe.getText,he.isXMLDoc=xe.isXML,he.contains=xe.contains,he.escapeSelector=xe.escape;var be=function(e,t,n){for(var r=[],i=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&he(e).is(n))break;r.push(e)}return r},we=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},Te=he.expr.match.needsContext,Ce=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,Ee=/^.[^:#\[\.,]*$/;he.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?he.find.matchesSelector(r,e)?[r]:[]:he.find.matches(e,he.grep(t,function(e){return 1===e.nodeType}))},he.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(he(e).filter(function(){for(t=0;t1?he.uniqueSort(n):n},filter:function(e){return this.pushStack(i(this,e||[],!1))},not:function(e){return this.pushStack(i(this,e||[],!0))},is:function(e){return!!i(this,"string"==typeof e&&Te.test(e)?he(e):e||[],!1).length}});var ke,Ne=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,Se=he.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||ke,"string"==typeof e){if(r="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:Ne.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof he?t[0]:t,he.merge(this,he.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:te,!0)),Ce.test(r[1])&&he.isPlainObject(t))for(r in t)he.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=te.getElementById(r[2]),i&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):he.isFunction(e)?void 0!==n.ready?n.ready(e):e(he):he.makeArray(e,this)};Se.prototype=he.fn,ke=he(te);var De=/^(?:parents|prev(?:Until|All))/,je={children:!0,contents:!0,next:!0,prev:!0};he.fn.extend({has:function(e){var t=he(e,this),n=t.length;return this.filter(function(){for(var e=0;e-1:1===n.nodeType&&he.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?he.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?ae.call(he(e),this[0]):ae.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(he.uniqueSort(he.merge(this.get(),he(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),he.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return be(e,"parentNode")},parentsUntil:function(e,t,n){return be(e,"parentNode",n)},next:function(e){return o(e,"nextSibling")},prev:function(e){return o(e,"previousSibling")},nextAll:function(e){return be(e,"nextSibling")},prevAll:function(e){return be(e,"previousSibling")},nextUntil:function(e,t,n){return be(e,"nextSibling",n)},prevUntil:function(e,t,n){return be(e,"previousSibling",n)},siblings:function(e){return we((e.parentNode||{}).firstChild,e)},children:function(e){return we(e.firstChild)},contents:function(e){return e.contentDocument||he.merge([],e.childNodes)}},function(e,t){he.fn[e]=function(n,r){var i=he.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=he.filter(r,i)),this.length>1&&(je[e]||he.uniqueSort(i),De.test(e)&&i.reverse()),this.pushStack(i)}});var Ae=/[^\x20\t\r\n\f]+/g;he.Callbacks=function(e){e="string"==typeof e?a(e):he.extend({},e);var t,n,r,i,o=[],s=[],u=-1,l=function(){for(i=e.once,r=t=!0;s.length;u=-1)for(n=s.shift();++u-1;)o.splice(n,1),n<=u&&u--}),this},has:function(e){return e?he.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=s=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=s=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=n||[],n=[e,n.slice?n.slice():n],s.push(n),t||l()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},he.extend({Deferred:function(t){var n=[["notify","progress",he.Callbacks("memory"),he.Callbacks("memory"),2],["resolve","done",he.Callbacks("once memory"),he.Callbacks("once memory"),0,"resolved"],["reject","fail",he.Callbacks("once memory"),he.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},catch:function(e){return i.then(null,e)},pipe:function(){var e=arguments;return he.Deferred(function(t){he.each(n,function(n,r){var i=he.isFunction(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&he.isFunction(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){function o(t,n,r,i){return function(){var l=this,c=arguments,f=function(){var e,f;if(!(t=a&&(r!==u&&(l=void 0,c=[e]),n.rejectWith(l,c))}};t?p():(he.Deferred.getStackHook&&(p.stackTrace=he.Deferred.getStackHook()),e.setTimeout(p))}}var a=0;return he.Deferred(function(e){n[0][3].add(o(0,e,he.isFunction(i)?i:s,e.notifyWith)),n[1][3].add(o(0,e,he.isFunction(t)?t:s)),n[2][3].add(o(0,e,he.isFunction(r)?r:u))}).promise()},promise:function(e){return null!=e?he.extend(e,i):i}},o={};return he.each(n,function(e,t){var a=t[2],s=t[5];i[t[1]]=a.add,s&&a.add(function(){r=s},n[3-e][2].disable,n[0][2].lock),a.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?void 0:this,arguments),this},o[t[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=re.call(arguments),o=he.Deferred(),a=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?re.call(arguments):n,--t||o.resolveWith(r,i)}};if(t<=1&&(l(e,o.done(a(n)).resolve,o.reject),"pending"===o.state()||he.isFunction(i[n]&&i[n].then)))return o.then();for(;n--;)l(i[n],a(n),o.reject);return o.promise()}});var qe=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;he.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&qe.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},he.readyException=function(t){e.setTimeout(function(){throw t})};var Le=he.Deferred();he.fn.ready=function(e){return Le.then(e).catch(function(e){he.readyException(e)}),this},he.extend({isReady:!1,readyWait:1,holdReady:function(e){e?he.readyWait++:he.ready(!0)},ready:function(e){(e===!0?--he.readyWait:he.isReady)||(he.isReady=!0,e!==!0&&--he.readyWait>0||Le.resolveWith(te,[he]))}}),he.ready.then=Le.then,"complete"===te.readyState||"loading"!==te.readyState&&!te.documentElement.doScroll?e.setTimeout(he.ready):(te.addEventListener("DOMContentLoaded",c),e.addEventListener("load",c));var He=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===he.type(n)){i=!0;for(s in n)He(e,t,s,n[s],!0,o,a)}else if(void 0!==r&&(i=!0,he.isFunction(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(he(e),n)})),t))for(;s1,null,!0)},removeData:function(e){return this.each(function(){Pe.remove(this,e)})}}),he.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Oe.get(e,t),n&&(!r||he.isArray(n)?r=Oe.access(e,t,he.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=he.queue(e,t),r=n.length,i=n.shift(),o=he._queueHooks(e,t),a=function(){he.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Oe.get(e,n)||Oe.access(e,n,{empty:he.Callbacks("once memory").add(function(){Oe.remove(e,[t+"queue",n])})})}}),he.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length\x20\t\r\n\f]+)/i,Ve=/^$|\/(?:java|ecma)script/i,Ge={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};Ge.optgroup=Ge.option,Ge.tbody=Ge.tfoot=Ge.colgroup=Ge.caption=Ge.thead,Ge.th=Ge.td;var Ye=/<|&#?\w+;/;!function(){var e=te.createDocumentFragment(),t=e.appendChild(te.createElement("div")),n=te.createElement("input");n.setAttribute("type","radio"),n.setAttribute("checked","checked"),n.setAttribute("name","t"),t.appendChild(n),pe.checkClone=t.cloneNode(!0).cloneNode(!0).lastChild.checked,t.innerHTML="",pe.noCloneChecked=!!t.cloneNode(!0).lastChild.defaultValue}();var Qe=te.documentElement,Je=/^key/,Ke=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ze=/^([^.]*)(?:\.(.+)|)/;he.event={global:{},add:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,m=Oe.get(e);if(m)for(n.handler&&(o=n,n=o.handler,i=o.selector),i&&he.find.matchesSelector(Qe,i),n.guid||(n.guid=he.guid++),(u=m.events)||(u=m.events={}),(a=m.handle)||(a=m.handle=function(t){return"undefined"!=typeof he&&he.event.triggered!==t.type?he.event.dispatch.apply(e,arguments):void 0}),t=(t||"").match(Ae)||[""],l=t.length;l--;)s=Ze.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d&&(f=he.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=he.event.special[d]||{},c=he.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&he.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||(p=u[d]=[],p.delegateCount=0,f.setup&&f.setup.call(e,r,h,a)!==!1||e.addEventListener&&e.addEventListener(d,a)),f.add&&(f.add.call(e,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),he.event.global[d]=!0)},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,m=Oe.hasData(e)&&Oe.get(e);if(m&&(u=m.events)){for(t=(t||"").match(Ae)||[""],l=t.length;l--;)if(s=Ze.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){for(f=he.event.special[d]||{},d=(r?f.delegateType:f.bindType)||d,p=u[d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;o--;)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&f.teardown.call(e,h,m.handle)!==!1||he.removeEvent(e,d,m.handle),delete u[d])}else for(d in u)he.event.remove(e,d+t[l],n,r,!0);he.isEmptyObject(u)&&Oe.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=he.event.fix(e),u=new Array(arguments.length),l=(Oe.get(this,"events")||{})[s.type]||[],c=he.event.special[s.type]||{};for(u[0]=s,t=1;t=1))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||l.disabled!==!0)){for(o=[],a={},n=0;n-1:he.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u\x20\t\r\n\f]*)[^>]*)\/>/gi,tt=/\s*$/g;he.extend({htmlPrefilter:function(e){return e.replace(et,"<$1>")},clone:function(e,t,n){var r,i,o,a,s=e.cloneNode(!0),u=he.contains(e.ownerDocument,e);if(!(pe.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||he.isXMLDoc(e)))for(a=v(s),o=v(e),r=0,i=o.length;r0&&y(a,!u&&v(e,"script")),s},cleanData:function(e){for(var t,n,r,i=he.event.special,o=0;void 0!==(n=e[o]);o++)if(Fe(n)){if(t=n[Oe.expando]){if(t.events)for(r in t.events)i[r]?he.event.remove(n,r):he.removeEvent(n,r,t.handle);n[Oe.expando]=void 0}n[Pe.expando]&&(n[Pe.expando]=void 0)}}}),he.fn.extend({detach:function(e){return A(this,e,!0)},remove:function(e){return A(this,e)},text:function(e){return He(this,function(e){return void 0===e?he.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return j(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=E(this,e);t.appendChild(e)}})},prepend:function(){return j(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=E(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return j(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return j(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(he.cleanData(v(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return he.clone(this,e,t)})},html:function(e){return He(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!tt.test(e)&&!Ge[(Ue.exec(e)||["",""])[1].toLowerCase()]){e=he.htmlPrefilter(e);try{for(;n1)}}),he.Tween=R,R.prototype={constructor:R,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||he.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(he.cssNumber[n]?"":"px")},cur:function(){var e=R.propHooks[this.prop];return e&&e.get?e.get(this):R.propHooks._default.get(this)},run:function(e){var t,n=R.propHooks[this.prop];return this.options.duration?this.pos=t=he.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):R.propHooks._default.set(this),this}},R.prototype.init.prototype=R.prototype,R.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=he.css(e.elem,e.prop,""),t&&"auto"!==t?t:0)},set:function(e){he.fx.step[e.prop]?he.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[he.cssProps[e.prop]]&&!he.cssHooks[e.prop]?e.elem[e.prop]=e.now:he.style(e.elem,e.prop,e.now+e.unit)}}},R.propHooks.scrollTop=R.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},he.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},he.fx=R.prototype.init,he.fx.step={};var dt,ht,gt=/^(?:toggle|show|hide)$/,mt=/queueHooks$/;he.Animation=he.extend(z,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return h(n.elem,e,We.exec(t),n),n}]},tweener:function(e,t){he.isFunction(e)?(t=e,e=["*"]):e=e.match(Ae);for(var n,r=0,i=e.length;r1)},removeAttr:function(e){return this.each(function(){he.removeAttr(this,e)})}}),he.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?he.prop(e,t,n):(1===o&&he.isXMLDoc(e)||(i=he.attrHooks[t.toLowerCase()]||(he.expr.match.bool.test(t)?vt:void 0)),void 0!==n?null===n?void he.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:(r=he.find.attr(e,t),null==r?void 0:r))},attrHooks:{type:{set:function(e,t){if(!pe.radioValue&&"radio"===t&&he.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(Ae);if(i&&1===e.nodeType)for(;n=i[r++];)e.removeAttribute(n)}}),vt={set:function(e,t,n){return t===!1?he.removeAttr(e,n):e.setAttribute(n,n),n}},he.each(he.expr.match.bool.source.match(/\w+/g),function(e,t){var n=yt[t]||he.find.attr;yt[t]=function(e,t,r){var i,o,a=t.toLowerCase();return r||(o=yt[a],yt[a]=i,i=null!=n(e,t,r)?a:null,yt[a]=o),i}});var xt=/^(?:input|select|textarea|button)$/i,bt=/^(?:a|area)$/i;he.fn.extend({prop:function(e,t){return He(this,he.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[he.propFix[e]||e]})}}),he.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&he.isXMLDoc(e)||(t=he.propFix[t]||t,i=he.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=he.find.attr(e,"tabindex");return t?parseInt(t,10):xt.test(e.nodeName)||bt.test(e.nodeName)&&e.href?0:-1}}},propFix:{for:"htmlFor",class:"className"}}),pe.optSelected||(he.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),he.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){he.propFix[this.toLowerCase()]=this}),he.fn.extend({addClass:function(e){var t,n,r,i,o,a,s,u=0;if(he.isFunction(e))return this.each(function(t){he(this).addClass(e.call(this,t,U(this)))});if("string"==typeof e&&e)for(t=e.match(Ae)||[];n=this[u++];)if(i=U(n),r=1===n.nodeType&&" "+X(i)+" "){for(a=0;o=t[a++];)r.indexOf(" "+o+" ")<0&&(r+=o+" ");s=X(r),i!==s&&n.setAttribute("class",s)}return this},removeClass:function(e){var t,n,r,i,o,a,s,u=0;if(he.isFunction(e))return this.each(function(t){he(this).removeClass(e.call(this,t,U(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof e&&e)for(t=e.match(Ae)||[];n=this[u++];)if(i=U(n),r=1===n.nodeType&&" "+X(i)+" "){for(a=0;o=t[a++];)for(;r.indexOf(" "+o+" ")>-1;)r=r.replace(" "+o+" "," ");s=X(r),i!==s&&n.setAttribute("class",s)}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):he.isFunction(e)?this.each(function(n){he(this).toggleClass(e.call(this,n,U(this),t),t)}):this.each(function(){var t,r,i,o;if("string"===n)for(r=0,i=he(this),o=e.match(Ae)||[];t=o[r++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else void 0!==e&&"boolean"!==n||(t=U(this),t&&Oe.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||e===!1?"":Oe.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;for(t=" "+e+" ";n=this[r++];)if(1===n.nodeType&&(" "+X(U(n))+" ").indexOf(t)>-1)return!0;return!1}});var wt=/\r/g;he.fn.extend({val:function(e){var t,n,r,i=this[0];return arguments.length?(r=he.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,he(this).val()):e,null==i?i="":"number"==typeof i?i+="":he.isArray(i)&&(i=he.map(i,function(e){return null==e?"":e+""})),t=he.valHooks[this.type]||he.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&void 0!==t.set(this,i,"value")||(this.value=i))})):i?(t=he.valHooks[i.type]||he.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&void 0!==(n=t.get(i,"value"))?n:(n=i.value,"string"==typeof n?n.replace(wt,""):null==n?"":n)):void 0}}),he.extend({valHooks:{option:{get:function(e){var t=he.find.attr(e,"value");return null!=t?t:X(he.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),he.each(["radio","checkbox"],function(){he.valHooks[this]={set:function(e,t){if(he.isArray(t))return e.checked=he.inArray(he(e).val(),t)>-1}},pe.checkOn||(he.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Tt=/^(?:focusinfocus|focusoutblur)$/;he.extend(he.event,{trigger:function(t,n,r,i){var o,a,s,u,l,c,f,p=[r||te],d=le.call(t,"type")?t.type:t,h=le.call(t,"namespace")?t.namespace.split("."):[];if(a=s=r=r||te,3!==r.nodeType&&8!==r.nodeType&&!Tt.test(d+he.event.triggered)&&(d.indexOf(".")>-1&&(h=d.split("."),d=h.shift(),h.sort()),l=d.indexOf(":")<0&&"on"+d,t=t[he.expando]?t:new he.Event(d,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=r),n=null==n?[t]:he.makeArray(n,[t]),f=he.event.special[d]||{},i||!f.trigger||f.trigger.apply(r,n)!==!1)){if(!i&&!f.noBubble&&!he.isWindow(r)){for(u=f.delegateType||d,Tt.test(u+d)||(a=a.parentNode);a;a=a.parentNode)p.push(a),s=a;s===(r.ownerDocument||te)&&p.push(s.defaultView||s.parentWindow||e)}for(o=0;(a=p[o++])&&!t.isPropagationStopped();)t.type=o>1?u:f.bindType||d,c=(Oe.get(a,"events")||{})[t.type]&&Oe.get(a,"handle"),c&&c.apply(a,n),c=l&&a[l],c&&c.apply&&Fe(a)&&(t.result=c.apply(a,n),t.result===!1&&t.preventDefault());return t.type=d,i||t.isDefaultPrevented()||f._default&&f._default.apply(p.pop(),n)!==!1||!Fe(r)||l&&he.isFunction(r[d])&&!he.isWindow(r)&&(s=r[l],s&&(r[l]=null),he.event.triggered=d,r[d](),he.event.triggered=void 0,s&&(r[l]=s)),t.result}},simulate:function(e,t,n){var r=he.extend(new he.Event,n,{type:e,isSimulated:!0});he.event.trigger(r,null,t)}}),he.fn.extend({trigger:function(e,t){return this.each(function(){he.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return he.event.trigger(e,t,n,!0)}}),he.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,t){he.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),he.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),pe.focusin="onfocusin"in e,pe.focusin||he.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){he.event.simulate(t,e.target,he.event.fix(e))};he.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=Oe.access(r,t);i||r.addEventListener(e,n,!0),Oe.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=Oe.access(r,t)-1;i?Oe.access(r,t,i):(r.removeEventListener(e,n,!0),Oe.remove(r,t))}}});var Ct=e.location,Et=he.now(),kt=/\?/;he.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||he.error("Invalid XML: "+t),n};var Nt=/\[\]$/,St=/\r?\n/g,Dt=/^(?:submit|button|image|reset|file)$/i,jt=/^(?:input|select|textarea|keygen)/i;he.param=function(e,t){var n,r=[],i=function(e,t){var n=he.isFunction(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(he.isArray(e)||e.jquery&&!he.isPlainObject(e))he.each(e,function(){i(this.name,this.value)});else for(n in e)V(n,e[n],t,i);return r.join("&")},he.fn.extend({serialize:function(){return he.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=he.prop(this,"elements");return e?he.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!he(this).is(":disabled")&&jt.test(this.nodeName)&&!Dt.test(e)&&(this.checked||!Xe.test(e))}).map(function(e,t){var n=he(this).val();return null==n?null:he.isArray(n)?he.map(n,function(e){return{name:t.name,value:e.replace(St,"\r\n")}}):{name:t.name,value:n.replace(St,"\r\n")}}).get()}});var At=/%20/g,qt=/#.*$/,Lt=/([?&])_=[^&]*/,Ht=/^(.*?):[ \t]*([^\r\n]*)$/gm,Ft=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Ot=/^(?:GET|HEAD)$/,Pt=/^\/\//,Rt={},Mt={},It="*/".concat("*"),Wt=te.createElement("a");Wt.href=Ct.href,he.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ct.href,type:"GET",isLocal:Ft.test(Ct.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":It,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":he.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Q(Q(e,he.ajaxSettings),t):Q(he.ajaxSettings,e)},ajaxPrefilter:G(Rt),ajaxTransport:G(Mt),ajax:function(t,n){function r(t,n,r,s){var l,p,d,b,w,T=n;c||(c=!0,u&&e.clearTimeout(u),i=void 0,a=s||"",C.readyState=t>0?4:0,l=t>=200&&t<300||304===t,r&&(b=J(h,C,r)),b=K(h,b,C,l),l?(h.ifModified&&(w=C.getResponseHeader("Last-Modified"),w&&(he.lastModified[o]=w),w=C.getResponseHeader("etag"),w&&(he.etag[o]=w)),204===t||"HEAD"===h.type?T="nocontent":304===t?T="notmodified":(T=b.state,p=b.data,d=b.error,l=!d)):(d=T,!t&&T||(T="error",t<0&&(t=0))),C.status=t,C.statusText=(n||T)+"",l?v.resolveWith(g,[p,T,C]):v.rejectWith(g,[C,T,d]),C.statusCode(x),x=void 0,f&&m.trigger(l?"ajaxSuccess":"ajaxError",[C,h,l?p:d]),y.fireWith(g,[C,T]),f&&(m.trigger("ajaxComplete",[C,h]),--he.active||he.event.trigger("ajaxStop")))}"object"==typeof t&&(n=t,t=void 0),n=n||{};var i,o,a,s,u,l,c,f,p,d,h=he.ajaxSetup({},n),g=h.context||h,m=h.context&&(g.nodeType||g.jquery)?he(g):he.event,v=he.Deferred(),y=he.Callbacks("once memory"),x=h.statusCode||{},b={},w={},T="canceled",C={readyState:0,getResponseHeader:function(e){var t;if(c){if(!s)for(s={};t=Ht.exec(a);)s[t[1].toLowerCase()]=t[2];t=s[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return c?a:null},setRequestHeader:function(e,t){return null==c&&(e=w[e.toLowerCase()]=w[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)C.always(e[C.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||T;return i&&i.abort(t),r(0,t),this}};if(v.promise(C),h.url=((t||h.url||Ct.href)+"").replace(Pt,Ct.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(Ae)||[""],null==h.crossDomain){l=te.createElement("a");try{l.href=h.url,l.href=l.href,h.crossDomain=Wt.protocol+"//"+Wt.host!=l.protocol+"//"+l.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=he.param(h.data,h.traditional)),Y(Rt,h,n,C),c)return C;f=he.event&&h.global,f&&0===he.active++&&he.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Ot.test(h.type),o=h.url.replace(qt,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(At,"+")):(d=h.url.slice(o.length),h.data&&(o+=(kt.test(o)?"&":"?")+h.data,delete h.data),h.cache===!1&&(o=o.replace(Lt,"$1"),d=(kt.test(o)?"&":"?")+"_="+Et++ +d),h.url=o+d),h.ifModified&&(he.lastModified[o]&&C.setRequestHeader("If-Modified-Since",he.lastModified[o]),he.etag[o]&&C.setRequestHeader("If-None-Match",he.etag[o])),(h.data&&h.hasContent&&h.contentType!==!1||n.contentType)&&C.setRequestHeader("Content-Type",h.contentType),C.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+It+"; q=0.01":""):h.accepts["*"]);for(p in h.headers)C.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(h.beforeSend.call(g,C,h)===!1||c))return C.abort();if(T="abort",y.add(h.complete),C.done(h.success),C.fail(h.error),i=Y(Mt,h,n,C)){if(C.readyState=1,f&&m.trigger("ajaxSend",[C,h]),c)return C;h.async&&h.timeout>0&&(u=e.setTimeout(function(){C.abort("timeout")},h.timeout));try{c=!1,i.send(b,r)}catch(e){if(c)throw e;r(-1,e)}}else r(-1,"No Transport");return C},getJSON:function(e,t,n){return he.get(e,t,n,"json")},getScript:function(e,t){return he.get(e,void 0,t,"script")}}),he.each(["get","post"],function(e,t){he[t]=function(e,n,r,i){return he.isFunction(n)&&(i=i||r,r=n,n=void 0),he.ajax(he.extend({url:e,type:t,dataType:i,data:n,success:r},he.isPlainObject(e)&&e))}}),he._evalUrl=function(e){return he.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,throws:!0})},he.fn.extend({wrapAll:function(e){var t;return this[0]&&(he.isFunction(e)&&(e=e.call(this[0])),t=he(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstElementChild;)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return he.isFunction(e)?this.each(function(t){he(this).wrapInner(e.call(this,t))}):this.each(function(){var t=he(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=he.isFunction(e);return this.each(function(n){he(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){he(this).replaceWith(this.childNodes)}),this}}),he.expr.pseudos.hidden=function(e){return!he.expr.pseudos.visible(e)},he.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},he.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var $t={0:200,1223:204},Bt=he.ajaxSettings.xhr();pe.cors=!!Bt&&"withCredentials"in Bt,pe.ajax=Bt=!!Bt,he.ajaxTransport(function(t){var n,r;if(pe.cors||Bt&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(a in i)s.setRequestHeader(a,i[a]);n=function(e){return function(){n&&(n=r=s.onload=s.onerror=s.onabort=s.onreadystatechange=null,"abort"===e?s.abort():"error"===e?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o($t[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=n(),r=s.onerror=n("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),he.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),he.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return he.globalEval(e),e}}}),he.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),he.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(r,i){t=he(" 82 | 83 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /templates/commit.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block head %} 5 | 7 | {% endblock %} 8 | 9 | {% block content %} 10 | {% if messages %} 11 |
    12 | {% for message in messages %} 13 | 14 | {% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}Important: {% endif %} 15 | {{ message }} 16 | 17 | {% endfor %} 18 |
19 | {% endif %} 20 |
21 | 22 |

23 | 24 |
25 | 26 |
27 |
28 | {% csrf_token %} 29 | 30 | {% for hidden_field in form.hidden_fields %} 31 | {{ hidden_field }} 32 | {% endfor %} 33 | 34 | {% if form.non_field_errors %} 35 | 40 | {% endif %} 41 | 42 | {% for field in form.visible_fields %} 43 |
44 | {{ field.label_tag }} 45 | 46 | {% if form.is_bound %} 47 | {% if field.errors %} 48 | {% render_field field class="form-control is-invalid" placeholder=field.label %} 49 | {% for error in field.errors %} 50 |
51 | {{ error }} 52 |
53 | {% endfor %} 54 | {% else %} 55 | {% render_field field class="form-control is-valid" placeholder=field.label %} 56 | {% endif %} 57 | {% else %} 58 | {% render_field field class="form-control" placeholder=field.label %} 59 | {% endif %} 60 | 61 | {% if field.help_text %} 62 | {{ field.help_text }} 63 | {% endif %} 64 |
65 | {% endfor %} 66 | 67 | 68 | 69 |
70 |
71 |
72 |
73 | 74 |
75 | {% endblock %} -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block content %} 3 |
4 | 5 | 8 |
9 | 10 |
11 |
12 | {% endblock %} 13 | --------------------------------------------------------------------------------