Compare commits

..

113 Commits

Author SHA1 Message Date
Naoki Takezoe
8a8278906a Bump to 4.19.2 2017-12-03 05:28:49 +09:00
Naoki Takezoe
d15b3fb2f6 Modify id of "Test Hook" button 2017-12-03 05:20:32 +09:00
Naoki Takezoe
bcd92916ca Fix routing in CompositeScalatraFilter 2017-12-03 04:36:05 +09:00
Naoki Takezoe
810cbda123 Update README.md 2017-12-03 02:17:27 +09:00
Naoki Takezoe
fee7cebdf1 Update README.md 2017-12-03 02:16:57 +09:00
Naoki Takezoe
28105d6d3a Update notification plugin 2017-12-03 01:00:40 +09:00
Naoki Takezoe
1673832607 Merge pull request #1786 from guyon/fix-repository-update-redirect-urlencode
fix redirect URL path encode
2017-12-02 18:39:45 +09:00
Naoki Takezoe
298e43e612 Update README.md and CHANGELOG.md 2017-12-02 18:26:52 +09:00
Naoki Takezoe
00b88d6b6e Update README.md and CHANGELOG.md 2017-12-02 18:16:17 +09:00
Naoki Takezoe
735123b93e Drop pages plugin from bundled plugins 2017-12-02 18:01:09 +09:00
Naoki Takezoe
fce3b3749c Update README.md and CHANGELOG.md 2017-12-02 03:11:22 +09:00
guyon
0a12b82b48 fix redirect URL path encode 2017-12-01 17:40:15 +09:00
Naoki Takezoe
9061d6bf7f (refs #1777) Bump gist plugin to 4.11.0 2017-11-29 11:23:43 +09:00
Naoki Takezoe
9ed8b554f3 Fix build.sbt 2017-11-29 10:17:48 +09:00
Naoki Takezoe
e306303cc8 Fix artifacts filter 2017-11-29 03:41:30 +09:00
Naoki Takezoe
c4bea091fe Update version to 4.19.0 2017-11-29 03:13:21 +09:00
Naoki Takezoe
2b383d79f1 Merge pull request #1778 from gitbucket/composite-filter
Introduce CompositeScalatraFilter to merge controllers to one filter
2017-11-29 00:43:30 +09:00
Naoki Takezoe
788e90469c Merge pull request #1784 from xuwei-k/sbt-1.0.4
sbt 1.0.4
2017-11-26 22:15:48 +09:00
kenji yoshida
f37711c816 sbt 1.0.4 2017-11-26 20:52:28 +09:00
Naoki Takezoe
f2c9d99f30 Merge branch 'master' into composite-filter 2017-11-23 14:05:55 +09:00
Naoki Takezoe
6073497e5e Fix validation rules for scalatra-forms 2017-11-23 14:00:55 +09:00
Naoki Takezoe
5d2ccfb0df Refactoring 2017-11-17 21:18:53 +09:00
Naoki Takezoe
3745243078 Mount filters with path 2017-11-17 18:23:41 +09:00
Naoki Takezoe
30a1968793 Handle plugin controllers by loop as same as CompositeScalatraFilter 2017-11-17 18:20:12 +09:00
Naoki Takezoe
581bcb3dc8 Introduce CompositeScalatraFilter to merge controllers to one filter 2017-11-17 17:44:35 +09:00
Naoki Takezoe
cd243f910a Merge pull request #1760 from gitbucket/scalatra-2.6
Bump to Scalatra 2.6.0
2017-11-16 16:53:10 +09:00
Naoki Takezoe
0b420177c4 Bump to Scalatra 2.6.1 2017-11-16 16:15:50 +09:00
Naoki Takezoe
0d8e022a0d Merge pull request #1773 from reap3r119/sidebar-post
Use POST for /sidebar-collapse
2017-11-15 13:27:42 +09:00
Naoki Takezoe
2f87d30359 Merge pull request #1775 from SIkebe/port-release-notes
Port Release Notes to CHANGELOG.md
2017-11-12 01:00:00 +09:00
Shodai Ikebe
98a5263a07 Port release notes to CHANGELOG.md 2017-11-11 02:42:16 +09:00
reap3r119
208f08c552 Use POST for /sidebar-collapse 2017-11-10 02:34:51 -05:00
Naoki Takezoe
b66852ec28 Fix for jQuery update 2017-11-10 16:15:41 +09:00
Naoki Takezoe
8d687660a9 Bump sbt to 1.0.3 2017-11-10 03:53:09 +09:00
Naoki Takezoe
c7749b281f Bump sbt-coursier to 1.0.0-RC13 2017-11-10 03:40:09 +09:00
Naoki Takezoe
ad5a0bb442 Use ex.toString instead of ex.getMessage to show exception type as well 2017-11-04 23:20:14 +01:00
Naoki Takezoe
6056642f69 Merge pull request #1765 from reap3r119/fix-proposals
Fix user proposals and update typeahead
2017-11-04 23:15:59 +01:00
Naoki Takezoe
21dcbf20b4 Merge pull request #1756 from reap3r119/admin-settings
Layout changes for System settings page
2017-11-04 22:41:53 +01:00
Naoki Takezoe
d92f0080ff Merge pull request #1759 from JD557/use-java-time
Replace joda-time with java.time
2017-11-04 22:36:27 +01:00
Naoki Takezoe
035cb170e0 Merge pull request #1764 from kounoike/pr-fix-1763
fix #1763 Don't delete close_comment
2017-11-04 22:35:25 +01:00
reap3r119
de5b2a9704 Resize labels, organize skins and add skin previewing 2017-11-03 09:12:54 -06:00
reap3r119
55f4b8c124 Fix user proposals and update typeahead 2017-11-03 09:10:27 -06:00
Naoki Takezoe
887baf2f08 Merge pull request #1761 from JD557/truncate-branch-name
Truncate long branch names
2017-11-02 15:02:02 +09:00
KOUNOIKE Yuusuke
bd63e1e75e fix #1763 when deleting comment, close_comment => close / reopen_comment => reopen. not delete. 2017-10-31 22:39:19 +09:00
João Costa
bc8dd4b3c2 Truncate long branch names
Fix #1135
2017-10-29 11:25:07 +00:00
Naoki Takezoe
15b348fd3d Bump to Scalatra 2.6.0 2017-10-29 14:47:25 +09:00
João Costa
5b5a644baa Replace joda-time with java.time
Fix #1513
2017-10-28 18:57:05 +01:00
Naoki Takezoe
fa2d7db0ca Merge pull request #1757 from reap3r119/patch-1
Rename PluginRegistory.scala to PluginRegistry.scala
2017-10-26 08:34:18 +09:00
Reap3r119
1893c212f3 Rename PluginRegistory.scala to PluginRegistry.scala 2017-10-25 11:39:46 -06:00
Naoki Takezoe
3c2dcb7b08 Bump to Scalatra 2.5.3 2017-10-25 12:24:37 +09:00
Naoki Takezoe
3d95679a1d Merge branch 'master' of https://github.com/gitbucket/gitbucket 2017-10-24 12:25:31 +09:00
Naoki Takezoe
29f380efa0 Bump to Scalatra 2.5.2 2017-10-24 12:23:58 +09:00
Naoki Takezoe
1da17940a2 Merge pull request #1755 from uli-heller/jetty947
Updated to jetty-9.4.7
2017-10-24 09:27:24 +09:00
Naoki Takezoe
348eada5b3 Merge pull request #1754 from uli-heller/mariadb212
Updated mariadb-java-client to 2.1.2
2017-10-24 01:30:51 +09:00
Naoki Takezoe
6f9450fece Fix bug in rendering of system menu icons 2017-10-23 15:27:29 +09:00
Uli Heller
2344ef7583 Updated to jetty-9.4.7 2017-10-22 20:32:51 +02:00
Uli Heller
b7b1befb27 Updated mariadb-java-client to 2.1.2 2017-10-22 19:21:40 +02:00
Naoki Takezoe
902f7ef95f Fix testcase 2017-10-22 21:33:42 +09:00
Naoki Takezoe
6bf71827f0 Fix plain text readme rendering 2017-10-22 20:31:01 +09:00
Naoki Takezoe
5a005cf5a6 Requests to H2 console don't need transaction 2017-10-22 19:45:43 +09:00
Naoki Takezoe
25729e3193 Merge pull request #1751 from kounoike/pr-delmove-from-repofilesdir
Delete/Move RepositoryFilesDir, instead of LFS/comments dir.
2017-10-22 02:25:54 +09:00
Naoki Takezoe
450b598f1f Bump notifications plugin to 1.3.0 2017-10-22 02:08:55 +09:00
Naoki Takezoe
f36bcef50c (refs #1748) Exclude gitbucket.war from published artifacts 2017-10-22 01:24:43 +09:00
Naoki Takezoe
86ff842eb2 Merge pull request #1752 from gitbucket/exclude-war-from-publish
(refs #1748) Exclude gitbucket.war from published artifacts
2017-10-21 19:10:11 +09:00
Naoki Takezoe
94ca597cf8 (refs #1748) Exclude gitbucket.war from published artifacts 2017-10-21 17:04:35 +09:00
Naoki Takezoe
e46e55f985 bump sbt-twirl to 1.3.12 2017-10-21 16:04:39 +09:00
Naoki Takezoe
50a63a8c87 Removed cancel button from the account settings page 2017-10-21 01:34:47 +09:00
KOUNOIKE Yuusuke
029d1a3a11 Delete/Move RepositoryFilesDir, instead of LFS/comments dir. 2017-10-20 20:12:10 +09:00
Naoki Takezoe
6df1b005bf Bump to 4.19.0-SNAPSHOT 2017-10-20 14:43:50 +09:00
Naoki Takezoe
e50082a9dd Merge pull request #1750 from uli-heller/scala2124
Updated to scala-2.12.4
2017-10-20 14:41:25 +09:00
Naoki Takezoe
9c4beca998 (refs #1749) Fix executable configuration 2017-10-20 14:40:14 +09:00
Uli Heller
d73cb094b6 Updated to scala-2.12.4 2017-10-20 07:13:00 +02:00
Naoki Takezoe
9e83882c6f Merge pull request #1742 from gitbucket/ssh-command-provider
Add new extension point: sshCommandProvider
2017-10-20 10:36:43 +09:00
Naoki Takezoe
d109ac0327 Merge pull request #1716 from gitbucket/sbt-1.0
Move to sbt 1.0
2017-10-20 01:41:34 +09:00
Naoki Takezoe
695fda4a73 Merge pull request #1746 from uli-heller/jgit490
jgit-4.9.0.201710071750-r
2017-10-20 01:22:59 +09:00
Naoki Takezoe
439d51bec1 Merge branch 'master' into sbt-1.0 2017-10-20 01:21:03 +09:00
Uli Heller
c3b89c96e0 jgit-4.9.0.201710071750-r 2017-10-19 13:53:38 +02:00
Naoki Takezoe
eb83c5713c Bump sbt-scalatra plugin to 1.0.1 2017-10-19 16:37:12 +09:00
Naoki Takezoe
58c22274ef Merge pull request #1738 from reap3r119/update-deps
Update dependencies for the web interface
2017-10-19 15:58:27 +09:00
reap3r119
bfd8c3a958 Use AdminLTE classes for logo
Use AdminLTE's 'logo-lg' and 'logo-mini' classes for the logo
instead of relying on hidden overflow
2017-10-17 15:05:05 -06:00
reap3r119
f402587a9a Update dependencies for the web interface 2017-10-17 09:07:01 -06:00
Naoki Takezoe
7736747d68 Add new extension point: sshCommandProvider 2017-10-17 17:11:26 +09:00
Naoki Takezoe
e6ee55e0a0 Merge pull request #1741 from gitbucket/encode-url-path
Encode file paths in URL
2017-10-16 21:15:05 +09:00
Naoki Takezoe
a2e8d24fdb Fix path encoding in JavaScript 2017-10-16 18:23:48 +09:00
Naoki Takezoe
9fb0d7eb40 Encode file paths in URL 2017-10-16 18:14:51 +09:00
Naoki Takezoe
24d4763fc8 Update README.md 2017-10-14 01:22:17 +09:00
Naoki Takezoe
e14a67e56d Merge pull request #1736 from reap3r119/local-fonts
Add local version of Source Sans Pro
2017-10-13 16:48:37 +09:00
reap3r119
d8fac332ab Remove nonexistent entries 2017-10-12 09:39:45 -06:00
reap3r119
c3ae06751e Move Source Sans to vendors and standardize folder layout 2017-10-12 09:38:11 -06:00
reap3r119
63ab1e3566 Fix EOT font file 2017-10-12 09:30:21 -06:00
reap3r119
c552b922b3 Delete unnecessary duplicates 2017-10-12 09:30:04 -06:00
reap3r119
d26f16ebdc Add local Source Sans Pro 2017-10-11 13:18:54 -06:00
Naoki Takezoe
cf18550a2c Bump emoji plugin to 4.5.0 2017-10-11 02:53:06 +09:00
Naoki Takezoe
8d2d3571b8 Update version to 4.18.0 2017-10-10 14:31:31 +09:00
Naoki Takezoe
d2ac5aa0bf Merge pull request #1734 from gitbucket/license-report
Create license report using sbt-license-report plugin
2017-10-10 14:15:50 +09:00
Naoki Takezoe
f1ae6784f5 Create license report 2017-10-10 13:09:20 +09:00
Naoki Takezoe
8a6448c64f Merge pull request #1733 from masterwto/master
Removes imports of external links so that gitbucket can be used in off-internet-environments
2017-10-10 10:17:23 +09:00
masterwto
98ccd4b1d4 Update AdminLTE.min.css
removes fonts.googleapis
2017-10-09 18:38:20 +08:00
masterwto
71b4a313e2 Update AdminLTE.css
removes fonts.googleapis
2017-10-09 18:37:48 +08:00
Naoki Takezoe
1bf6939fc3 Merge pull request #1732 from gitbucket/reply-diff-comment
Add reply comment form to diff view
2017-10-09 12:48:38 +09:00
Naoki Takezoe
0000949966 Adding reply comment form to diff view 2017-10-09 12:29:32 +09:00
Naoki Takezoe
f767e621a4 Fix CSS style 2017-10-09 03:31:38 +09:00
Naoki Takezoe
d40c8ff6eb Merge pull request #1731 from gitbucket/enhance-suggestion-provider
Enhance SuggestionProvider to be able to supply label and value
2017-10-09 00:30:36 +09:00
Naoki Takezoe
e6838d8891 Enhance SuggestionProvider to be able to supply label and value 2017-10-08 14:35:23 +09:00
Naoki Takezoe
440dd0386b Merge pull request #1715 from kounoike/pr-use-fullname-for-edit
Use account.fullName instead of userName for Web UI edit, Wiki uploads.
2017-10-08 13:06:46 +09:00
Naoki Takezoe
37b181c5d0 (refs #1725) Allow administrators in collaborators to force to merge PR 2017-10-08 04:17:20 +09:00
Naoki Takezoe
5e7afa0f41 (refs #1727) Repair the commit diff view 2017-10-04 18:16:56 +09:00
Naoki Takezoe
badc9b5117 Merge pull request #1726 from reap3r119/patch-1
Add additional system paths to reserved names
2017-10-03 01:55:00 +09:00
Naoki Takezoe
5257c4fc2c Apply commit hook to online editing (#1729)
Apply commit hook to online file editing
2017-10-03 01:52:30 +09:00
Reap3r119
f47e389a9b Reserve "groups" and "new" 2017-09-29 12:34:30 -06:00
Reap3r119
8327333305 Reserve additional system paths 2017-09-29 12:13:15 -06:00
Reap3r119
4bd05835a5 Reserve "assets" and "plugin-assets" 2017-09-29 11:57:56 -06:00
Naoki Takezoe
1a9982446f Move to sbt 1.0 2017-09-21 13:27:14 +09:00
KOUNOIKE Yuusuke
407c742596 Use account.fullName instead of userName for Web UI edit, Wiki uploads. 2017-09-19 23:06:04 +09:00
239 changed files with 12070 additions and 11848 deletions

432
CHANGELOG.md Normal file
View File

@@ -0,0 +1,432 @@
# Changelog
All changes to the project will be documented in this file.
## 4.19.0 - 2 Dec 2017
- [gitbucket-maven-repository-plugin](https://github.com/takezoe/gitbucket-maven-repository-plugin) is available
- Upgrade to Scalatra 2.6
- Improve layout of the system settings page
- New extension point (`sshCommandProvider`)
- Dropped [gitbucket-pages-plugin](https://github.com/gitbucket/gitbucket-pages-plugin) from bundled plugins temporary because we couldn't complete update for Scalatra 2.6 before this release.
## 4.18.0 - 14 Oct 2017
- Form to reply to review comment
- Display fullname in username suggestion
- Commit hook plugins are applied to online editing
- Improve gitbucket-ci-plugin
## 4.17.0 - 30 Sep 2017
- [gitbucket-ci-plugin](https://github.com/takezoe/gitbucket-ci-plugin) is available
- Transferring to URL with commit ID
- Drop uploadable file type limitation
- Improve Mailer API
- Web API and webhook enhancement
## 4.16.0 - 2 Sep 2017
- Support AdminLTE color skin
- Improve unexpected error handling
- Show commit status on the commits list
## 4.15.0 - 5 Aug 2017
- Bundle GitBucket organization plugins
- Notifications plugin
- Plugin hot deployment
- Update Slick to 3.2.1 from 3.2.0
- Support ed25519 keys for SSH
- Markdown preview in comment editing forms
## 4.14.1 - 4 Jul 2017
- Bug fix: Possibility of error in forking repository
## 4.14 - 1 Jul 2017
- Support priority in issues and pull requests
- Show icons when the sidebar is collapsed
- Support gollum events in web hook
- Support account (user / group) level web hook
- Add `--max_file_size` option
- Configuration by system property or environment variable
## 4.13 - 29 May 2017
- Uploading files into the repository
- HTML is available in Markdown
- Added filter box to dropdown menus
## 4.12 - 30 Apr 2017
- [Gist plug-in](https://github.com/gitbucket/gitbucket-gist-plugin) provides JavaScript to embed snippet
- Dropdown menu filter in the branch comparing page
- Caution for the embedded H2 database
## 4.11 - 1 Apr 2017
- Deploy keys support
- Auto generate avatar images
- Collaborators of the private forked repository are copied from the original repository
- Cache avatar images in the browser
- New extension point to receive events about repository
## 4.10 - 25 Feb 2017
- Update to Scala 2.12, Scalatra 2.5 and Slick 3.2
- Display file size in the file viewer
## 4.9 - 29 Jan 2017
- GitLFS support
- Template for issues and pull requests
- Manual label color editing
- Account description
- `--tmp-dir` option for standalone mode
- More APIs for issues
- [List issues for a repository](https://developer.github.com/v3/issues/#list-issues-for-a-repository)
- [Create an issue](https://developer.github.com/v3/issues/#create-an-issue)
## 4.8 - 23 Dec 2016
- Search for repository names from the global header
- Filter repositories on the sidebar of the dashboard
- Search issues and wiki
- Keep pull request comments after new commits are pushed
- New web API to get a single issue
- Performance improvement for the repository viewer
## 4.7.1 - 28 Nov 2016
- Bug fix: group repositories are not shown in the your repositories list on the sidebar
- Small performance improvement of the dashboard
## 4.7 - 26 Nov 2016
- New permission system
- Dropdown filter for issue labels, milestones and assignees
- Keep sidebar folding status
- Link from milestone label to the issue list
## 4.6 - 29 Oct 2016
- Add disable option for forking
- Add History button to wiki page
- Git repository URL redirection for GitHub compatibility
- Get-Content API improvement
- Indicate who is group master in Members tab in group view
## 4.5 - 29 Sep 2016
- Attach files by dropping into textarea
- Issues / Pull requests switcher in dashboard
- HikariCP could be configured in `GITBUCKET_HOME/database.conf`
- Improve Cookie security
- Display commit count on the history button
- Improve mobile view
## 4.4 - 28 Aug 2016
- Import a SQL dump file to the database
- `go get` support in private repositories
- Sort milestones by due date
- apache-sshd has been updated to 1.2.0
## 4.3 - 30 Jul 2016
- Emoji support by [gitbucket-emoji-plugin](https://github.com/gitbucket/gitbucket-emoji-plugin)
- User name suggestion
- Add new web APIs and basic authentication support for API access
- Root Endpoint
- [List endpoints](https://developer.github.com/v3/#root-endpoint)
- [List Branches](https://developer.github.com/v3/repos/branches/#list-branches)
- [Get contents](https://developer.github.com/v3/repos/contents/#get-contents)
- [Get a Reference](https://developer.github.com/v3/git/refs/#get-a-reference)
- [List Collaborators](https://developer.github.com/v3/repos/collaborators/#list-collaborators)
- [List user repositories](https://developer.github.com/v3/repos/#list-user-repositories)
- [Get a group](https://developer.github.com/v3/orgs/#get-an-organization)
- [List group repositories](https://developer.github.com/v3/repos/#list-organization-repositories)
- Add new extension points
- `assetsMapping` : Supplies resources in plugin classpath as web assets
- `suggestionProvider` : Provides suggestion in the Markdown editing textarea
- `textDecorator` : Decorate text nodes in HTML which is converted from Markdown
## 4.2.1 - 3 Jul 2016
- Fix migration bug
This is hotfix for a critical bug in migration. If you are new installation, use 4.2.0. But if you have an exisiting installation and it had been updated to 4.0 from 3.x, you must update to 4.2.1.
## 4.2 - 2 Jul 2016
- New UI based on [AdminLTE](https://github.com/almasaeed2010/AdminLTE)
- git gc
- Issues and Wiki have been possible to be disabled
- SMTP configuration test mail
## 4.1 - 4 Jun 2016
- Generic ssh user
- Improve branch protection UI
- Default value of pull request title
## 4.0 - 30 Apr 2016
- MySQL and PostgreSQL support
- Data export and import
- Migration system has been switched to [solidbase](https://github.com/gitbucket/solidbase)
**Note:** You can upgrade to GitBucket 4.0 from 3.14. If your GitBucket is 3.13 or before, you have to upgrade 3.14 at first.
## 3.14 - 30 Apr 2016
- File attachment and search for wiki pages
- New extension points to add menus
- Content-Type of webhooks has been choosable
## 3.13 - 1 Apr 2016
- Refresh user interface for wide screen
- Add `pull_request` key in list issues API for pull requests
- Add `X-Hub-Signature` security to webhooks
- Provide SHA-256 checksum for `gitbucket.war`
## 3.12 - 27 Feb 2016
- New GitHub UI
- Improve mobile view
- Improve printing style
- Individual URL for pull request tabs
- SSH host configuration is separated from HTTP base URL
## 3.11 - 30 Jan 2016
- Upgrade Scalatra to 2.4
- Sidebar and Footer for Wiki
- Branch protection and receive hook extension point for plug-in
- Limit recent updated repositories list
- Issue actions look-alike GitHub
- Web API for labels
- Requires Java 8
## 3.10 - 30 Dec 2015
- Move to Bootstrap3
- New URL for raw contents (`raw/master/doc/activity.md` instead of `blob/master/doc/activity.md?raw=true`)
- Update xsbt-web-plugin
- Update H2 database
## 3.9 - 5 Dec 2015
- GFM inline breaks support in Markdown
- WebHook on create review comment is available
- WebHook event trigger is selectable
## 3.8 - 31 Oct 2015
- Moved to GitHub organization
- Omit diff view for large differences
- Repository creation API
- Render url as link in repository description
- Expand attachable file types
## 3.7 - 3 Oct 2015
- Markdown processor has been switched to [markedj](https://github.com/gitbucket/markedj) from pegdown
- Clone in desktop button
- Providing MD5 and SHA-1 checksum for `gitbucket.war` has started
## 3.6 - 30 Aug 2015
- User interface Improvements: Especially, commit list, issues and pull request have been updated largely.
- Installed plugins list has been available at the system administration console.
- Pages and repository list in the sidebar have been limited and more pages and repositories link is available.
- More reference link notation in Markdown has been supported.
## 3.5 - 1 Aug 2015
- Octicons has been applied
- Global header has been enhanced. Now it's further similar to GitHub.
- Default compare / pull request target has been changed to the parent repository
- A lot of updates for [gitbucket-gist-plugin](https://github.com/gitbucket/gitbucket-gist-plugin)
## 3.4 - 27 Jun 2015
- Declarative style plug-in definition
- New extension point to add markup render
- go-import support
## 3.3 - 31 May 2015
- Rich graphical diff for images
- File finder is available in the repository viewer
- Blame is displayed at the source viewer
- Remain user data and repositories even if user is disabled
- Mobile view improvement
## 3.2 - 3 May 2015
- Directory history button
- Compare / pull request button
- Limit of activity log
## 3.1.1 - 4 Apr 2015
- Rolled back H2 version to avoid version compatibility issue
- Plug-ins became possible to access ServletContext
## 3.1 - 28 Mar 2015
- Web APIs for Jenkins github pull-request builder
- Improved diff view
- Bump Scalatra to 2.3.1, sbt to 0.13.8
## 3.0 - 3 Mar 2015
- New plug-in system is available
- Connection pooling by c3p0
- New branch UI
- Compare between specified commit ids
## 2.8 - 1 Feb 2015
- New logo and icons
- New system setting options to control visibility
- Comment on side-by-side diff
- Information message on sign-in page
- Fork repository by group account
## 2.7 - 29 Dec 2014
- Comment for commit and diff
- Fix security issue in markdown rendering
- Some bug fix and improvements
## 2.6 - 24 Nov 2014
- Search box at issues and pull requests
- Information from administrator
- Pull request UI has been updated
- Move to TravisCI from Buildhive
- Some bug fix and improvements
## 2.5 - 4 Nov 2014
- New Dashboard
- Change datetime format
- Create branch from Web UI
- Task list in Markdown
- Some bug fix and improvements
## 2.4.1 - 6 Oct 2014
- Bug fix
## 2.4 - 6 Oct 2014
- New UI is applied to Issues and Pull requests
- Side-by-side diff is available
- Fix relative path problem in Markdown links and images
- Plugin System is disabled in default
- Some bug fix and improvements
## 2.3 - 1 Sep 2014
- Scala based plugin system
- Embedded Jetty war extraction directory moved to `GITBUCKET_HOME/tmp`
- Some bug fix and improvements
## 2.2.1 - 5 Aug 2014
- Bug fix
## 2.2 - 4 Aug 2014
- Plug-in system is available
- Move to Scala 2.11, Scalatra 2.3 and Slick 2.1
- tar.gz export for repository contents
- LDAP authentication improvement (mail address became optional)
- Show news feed of a private repository to members
- Some bug fix and improvements
## 2.1 - 6 Jul 2014
- Upgrade to Slick 2.0 from 1.9
- Base part of the plug-in system is merged
- Many bug fix and improvements
## 2.0 - 31 May 2014
- Modern Github UI
- Preview in AceEditor
- Select lines by clicking line number in blob view
## 1.13 - 29 Apr 2014
- Direct file editing in the repository viewer using AceEditor
- File attachment for issues
- Atom feed of user activity
- Fix some bugs
## 1.12 - 29 Mar 2014
- SSH repository access is available
- Allow users can create and management their groups
- Git submodule support
- Close issues via commit messages
- Show repository description below the name on repository page
- Fix presentation of the source viewer
- Upgrade to sbt 0.13
- Fix some bugs
## 1.11.1 - 06 Mar 2014
- Bug fix
## 1.11 - 01 Mar 2014
- Base URL for redirection, notification and repository URL box is configurable
- Remove ```--https``` option because it's possible to substitute in the base url
- Headline anchor is available for Markdown contents such as Wiki page
- Improve H2 connectivity
- Label is available for pull requests not only issues
- Delete branch button is added
- Repository icons are updated
- Select lines of source code by URL hash like `#L10` or `#L10-L15` in repository viewer
- Display reference to issue from others in comment list
- Fix some bugs
## 1.10 - 01 Feb 2014
- Rename repository
- Transfer repository owner
- Change default data directory to `HOME/.gitbucket` from `HOME/gitbucket` to avoid problem like #243, but if data directory already exist at HOME/gitbucket, it continues being used.
- Add LDAP display name attribute
- Response performance improvement
- Fix some bugs
## 1.9 - 28 Dec 2013
- Display GITBUCKET_HOME on the system settings page
- Fix some bugs
## 1.8 - 30 Nov 2013
- Add user and group deletion
- Improve pull request performance
- Pull request synchronization (when source repository is updated after pull request, it's applied to the pull request)
- LDAP StartTLS support
- Enable hard wrapping in Markdown
- Add new some options to specify the data directory. See details in [Wiki](https://github.com/takezoe/gitbucket/wiki/DirectoryStructure).
- Fix some bugs
## 1.7 - 26 Oct 2013
- Support working on Java6 in embedded Jetty mode
- Add `--host` option to bind specified host name in embedded Jetty mode
- Add `--https=true` option to force https scheme when using embedded Jetty mode at the back of https proxy
- Add full name as user property
- Change link color for absent Wiki pages
- Add ZIP download button to the repository viewer tab
- Improve ZIP exporting performance
- Expand issue and comment textarea for long text automatically
- Add conflict detection in Wiki
- Add reverting wiki page from history
- Match committer to user name by email address
- Mail notification sender is customizable
- Add link to changeset in refs comment for issues
- Fix some bugs
## 1.6 - 1 Oct 2013
- Web hook
- Performance improvement for pull request
- Executable war file
- Specify suitable Content-Type for downloaded files in the repository viewer
- Fix some bugs
## 1.5 - 4 Sep 2013
- Fork and pull request
- LDAP authentication
- Mail notification
- Add an option to turn off the gravatar support
- Add the branch tab in the repository viewer
- Encoding auto detection for the file content in the repository viewer
- Add favicon, header logo and icons for the timeline
- Specify data directory via environment variable GITBUCKET_HOME
- Fix some bugs
## 1.4 - 31 Jul 2013
- Group management
- Repository search for code and issues
- Display user related issues on the dashboard
- Display participants avatar of issues on the issue page
- Performance improvement for repository viewer
- Alert by milestone due date
- H2 database administration console
- Fix some bugs
## 1.3 - 18 Jul 2013
- Batch updating for issues
- Display assigned user on issue list
- User icon and Gravatar support
- Convert @xxxx to link to the account page
- Add copy to clipboard button for git clone URL
- Allow multi-byte characters as wiki page name
- Allow to create the empty repository
- Fix some bugs
## 1.2 - 09 Jul 2013
- Add activity timeline
- Bugfix for Git 1.8.1.5 or later
- Allow multi-byte characters as label
- Fix some bugs
## 1.1 - 05 Jul 2013
- Fix some bugs
- Upgrade to JGit 3.0
## 1.0 - 04 Jul 2013
- This is a first public release

423
README.md
View File

@@ -68,421 +68,24 @@ Support
- If you can't find same question and report, send it to [gitter room](https://gitter.im/gitbucket/gitbucket) before raising an issue.
- The highest priority of GitBucket is the ease of installation and API compatibility with GitHub, so your feature request might be rejected if they go against those principles.
Release Notes
What's New in 4.19.x
-------------
### 4.17.0 - 30 Sep 2017
- [gitbucket-ci-plugin](https://github.com/takezoe/gitbucket-ci-plugin) is available
- Transferring to URL with commit ID
- Drop uploadable file type limitation
- Improve Mailer API
- Web API and webhook enhancement
### 4.16.0 - 2 Sep 2017
- Support AdminLTE color skin
- Improve unexpected error handling
- Show commit status on the commits list
### 4.19.2 - 3 Dec 2017
### 4.15.0 - 5 Aug 2017
- Bundle GitBucket organization plugins
- Notifications plugin
- Plugin hot deployment
- Update Slick to 3.2.1 from 3.2.0
- Support ed25519 keys for SSH
- Markdown preview in comment editing forms
- Fix routing bug in `CompositeScalatraFilter`
- Resolve id attribute collision in the web hook editing form
### 4.14.1 - 4 Jul 2017
- Bug fix: Possibility of error in forking repository
### 4.19.1 - 2 Dec 2017
### 4.14 - 1 Jul 2017
- Support priority in issues and pull requests
- Show icons when the sidebar is collapsed
- Support gollum events in web hook
- Support account (user / group) level web hook
- Add `--max_file_size` option
- Configuration by system property or environment variable
- Update gitbucket-notifications-plugin because it had a version compatibility issue
### 4.13 - 29 May 2017
- Uploading files into the repository
- HTML is available in Markdown
- Added filter box to dropdown menus
### 4.19.0 - 2 Dec 2017
### 4.12 - 30 Apr 2017
- [Gist plug-in](https://github.com/gitbucket/gitbucket-gist-plugin) provides JavaScript to embed snippet
- Dropdown menu filter in the branch comparing page
- Caution for the embedded H2 database
- [gitbucket-maven-repository-plugin](https://github.com/takezoe/gitbucket-maven-repository-plugin) is available
- Upgrade to Scalatra 2.6
- Improve layout of the system settings page
- New extension point (`sshCommandProvider`)
- Dropped [gitbucket-pages-plugin](https://github.com/gitbucket/gitbucket-pages-plugin) from bundled plugins temporary because we couldn't complete update for Scalatra 2.6 before this release.
### 4.11 - 1 Apr 2017
- Deploy keys support
- Auto generate avatar images
- Collaborators of the private forked repository are copied from the original repository
- Cache avatar images in the browser
- New extension point to receive events about repository
### 4.10 - 25 Feb 2017
- Update to Scala 2.12, Scalatra 2.5 and Slick 3.2
- Display file size in the file viewer
### 4.9 - 29 Jan 2017
- GitLFS support
- Template for issues and pull requests
- Manual label color editing
- Account description
- `--tmp-dir` option for standalone mode
- More APIs for issues
- [List issues for a repository](https://developer.github.com/v3/issues/#list-issues-for-a-repository)
- [Create an issue](https://developer.github.com/v3/issues/#create-an-issue)
### 4.8 - 23 Dec 2016
- Search for repository names from the global header
- Filter repositories on the sidebar of the dashboard
- Search issues and wiki
- Keep pull request comments after new commits are pushed
- New web API to get a single issue
- Performance improvement for the repository viewer
### 4.7.1 - 28 Nov 2016
- Bug fix: group repositories are not shown in the your repositories list on the sidebar
- Small performance improvement of the dashboard
### 4.7 - 26 Nov 2016
- New permission system
- Dropdown filter for issue labels, milestones and assignees
- Keep sidebar folding status
- Link from milestone label to the issue list
### 4.6 - 29 Oct 2016
- Add disable option for forking
- Add History button to wiki page
- Git repository URL redirection for GitHub compatibility
- Get-Content API improvement
- Indicate who is group master in Members tab in group view
### 4.5 - 29 Sep 2016
- Attach files by dropping into textarea
- Issues / Pull requests switcher in dashboard
- HikariCP could be configured in `GITBUCKET_HOME/database.conf`
- Improve Cookie security
- Display commit count on the history button
- Improve mobile view
### 4.4 - 28 Aug 2016
- Import a SQL dump file to the database
- `go get` support in private repositories
- Sort milestones by due date
- apache-sshd has been updated to 1.2.0
### 4.3 - 30 Jul 2016
- Emoji support by [gitbucket-emoji-plugin](https://github.com/gitbucket/gitbucket-emoji-plugin)
- User name suggestion
- Add new web APIs and basic authentication support for API access
- Root Endpoint
- [List endpoints](https://developer.github.com/v3/#root-endpoint)
- [List Branches](https://developer.github.com/v3/repos/branches/#list-branches)
- [Get contents](https://developer.github.com/v3/repos/contents/#get-contents)
- [Get a Reference](https://developer.github.com/v3/git/refs/#get-a-reference)
- [List Collaborators](https://developer.github.com/v3/repos/collaborators/#list-collaborators)
- [List user repositories](https://developer.github.com/v3/repos/#list-user-repositories)
- [Get a group](https://developer.github.com/v3/orgs/#get-an-organization)
- [List group repositories](https://developer.github.com/v3/repos/#list-organization-repositories)
- Add new extension points
- `assetsMapping` : Supplies resources in plugin classpath as web assets
- `suggestionProvider` : Provides suggestion in the Markdown editing textarea
- `textDecorator` : Decorate text nodes in HTML which is converted from Markdown
### 4.2.1 - 3 Jul 2016
- Fix migration bug
This is hotfix for a critical bug in migration. If you are new installation, use 4.2.0. But if you have an exisiting installation and it had been updated to 4.0 from 3.x, you must update to 4.2.1.
### 4.2 - 2 Jul 2016
- New UI based on [AdminLTE](https://github.com/almasaeed2010/AdminLTE)
- git gc
- Issues and Wiki have been possible to be disabled
- SMTP configuration test mail
### 4.1 - 4 Jun 2016
- Generic ssh user
- Improve branch protection UI
- Default value of pull request title
### 4.0 - 30 Apr 2016
- MySQL and PostgreSQL support
- Data export and import
- Migration system has been switched to [solidbase](https://github.com/gitbucket/solidbase)
**Note:** You can upgrade to GitBucket 4.0 from 3.14. If your GitBucket is 3.13 or before, you have to upgrade 3.14 at first.
### 3.14 - 30 Apr 2016
- File attachment and search for wiki pages
- New extension points to add menus
- Content-Type of webhooks has been choosable
### 3.13 - 1 Apr 2016
- Refresh user interface for wide screen
- Add `pull_request` key in list issues API for pull requests
- Add `X-Hub-Signature` security to webhooks
- Provide SHA-256 checksum for `gitbucket.war`
### 3.12 - 27 Feb 2016
- New GitHub UI
- Improve mobile view
- Improve printing style
- Individual URL for pull request tabs
- SSH host configuration is separated from HTTP base URL
### 3.11 - 30 Jan 2016
- Upgrade Scalatra to 2.4
- Sidebar and Footer for Wiki
- Branch protection and receive hook extension point for plug-in
- Limit recent updated repositories list
- Issue actions look-alike GitHub
- Web API for labels
- Requires Java 8
### 3.10 - 30 Dec 2015
- Move to Bootstrap3
- New URL for raw contents (`raw/master/doc/activity.md` instead of `blob/master/doc/activity.md?raw=true`)
- Update xsbt-web-plugin
- Update H2 database
### 3.9 - 5 Dec 2015
- GFM inline breaks support in Markdown
- WebHook on create review comment is available
- WebHook event trigger is selectable
### 3.8 - 31 Oct 2015
- Moved to GitHub organization
- Omit diff view for large differences
- Repository creation API
- Render url as link in repository description
- Expand attachable file types
### 3.7 - 3 Oct 2015
- Markdown processor has been switched to [markedj](https://github.com/gitbucket/markedj) from pegdown
- Clone in desktop button
- Providing MD5 and SHA-1 checksum for `gitbucket.war` has started
### 3.6 - 30 Aug 2015
- User interface Improvements: Especially, commit list, issues and pull request have been updated largely.
- Installed plugins list has been available at the system administration console.
- Pages and repository list in the sidebar have been limited and more pages and repositories link is available.
- More reference link notation in Markdown has been supported.
### 3.5 - 1 Aug 2015
- Octicons has been applied
- Global header has been enhanced. Now it's further similar to GitHub.
- Default compare / pull request target has been changed to the parent repository
- A lot of updates for [gitbucket-gist-plugin](https://github.com/gitbucket/gitbucket-gist-plugin)
### 3.4 - 27 Jun 2015
- Declarative style plug-in definition
- New extension point to add markup render
- go-import support
### 3.3 - 31 May 2015
- Rich graphical diff for images
- File finder is available in the repository viewer
- Blame is displayed at the source viewer
- Remain user data and repositories even if user is disabled
- Mobile view improvement
### 3.2 - 3 May 2015
- Directory history button
- Compare / pull request button
- Limit of activity log
### 3.1.1 - 4 Apr 2015
- Rolled back H2 version to avoid version compatibility issue
- Plug-ins became possible to access ServletContext
### 3.1 - 28 Mar 2015
- Web APIs for Jenkins github pull-request builder
- Improved diff view
- Bump Scalatra to 2.3.1, sbt to 0.13.8
### 3.0 - 3 Mar 2015
- New plug-in system is available
- Connection pooling by c3p0
- New branch UI
- Compare between specified commit ids
### 2.8 - 1 Feb 2015
- New logo and icons
- New system setting options to control visibility
- Comment on side-by-side diff
- Information message on sign-in page
- Fork repository by group account
### 2.7 - 29 Dec 2014
- Comment for commit and diff
- Fix security issue in markdown rendering
- Some bug fix and improvements
### 2.6 - 24 Nov 2014
- Search box at issues and pull requests
- Information from administrator
- Pull request UI has been updated
- Move to TravisCI from Buildhive
- Some bug fix and improvements
### 2.5 - 4 Nov 2014
- New Dashboard
- Change datetime format
- Create branch from Web UI
- Task list in Markdown
- Some bug fix and improvements
### 2.4.1 - 6 Oct 2014
- Bug fix
### 2.4 - 6 Oct 2014
- New UI is applied to Issues and Pull requests
- Side-by-side diff is available
- Fix relative path problem in Markdown links and images
- Plugin System is disabled in default
- Some bug fix and improvements
### 2.3 - 1 Sep 2014
- Scala based plugin system
- Embedded Jetty war extraction directory moved to `GITBUCKET_HOME/tmp`
- Some bug fix and improvements
### 2.2.1 - 5 Aug 2014
- Bug fix
### 2.2 - 4 Aug 2014
- Plug-in system is available
- Move to Scala 2.11, Scalatra 2.3 and Slick 2.1
- tar.gz export for repository contents
- LDAP authentication improvement (mail address became optional)
- Show news feed of a private repository to members
- Some bug fix and improvements
### 2.1 - 6 Jul 2014
- Upgrade to Slick 2.0 from 1.9
- Base part of the plug-in system is merged
- Many bug fix and improvements
### 2.0 - 31 May 2014
- Modern Github UI
- Preview in AceEditor
- Select lines by clicking line number in blob view
### 1.13 - 29 Apr 2014
- Direct file editing in the repository viewer using AceEditor
- File attachment for issues
- Atom feed of user activity
- Fix some bugs
### 1.12 - 29 Mar 2014
- SSH repository access is available
- Allow users can create and management their groups
- Git submodule support
- Close issues via commit messages
- Show repository description below the name on repository page
- Fix presentation of the source viewer
- Upgrade to sbt 0.13
- Fix some bugs
### 1.11.1 - 06 Mar 2014
- Bug fix
### 1.11 - 01 Mar 2014
- Base URL for redirection, notification and repository URL box is configurable
- Remove ```--https``` option because it's possible to substitute in the base url
- Headline anchor is available for Markdown contents such as Wiki page
- Improve H2 connectivity
- Label is available for pull requests not only issues
- Delete branch button is added
- Repository icons are updated
- Select lines of source code by URL hash like `#L10` or `#L10-L15` in repository viewer
- Display reference to issue from others in comment list
- Fix some bugs
### 1.10 - 01 Feb 2014
- Rename repository
- Transfer repository owner
- Change default data directory to `HOME/.gitbucket` from `HOME/gitbucket` to avoid problem like #243, but if data directory already exist at HOME/gitbucket, it continues being used.
- Add LDAP display name attribute
- Response performance improvement
- Fix some bugs
### 1.9 - 28 Dec 2013
- Display GITBUCKET_HOME on the system settings page
- Fix some bugs
### 1.8 - 30 Nov 2013
- Add user and group deletion
- Improve pull request performance
- Pull request synchronization (when source repository is updated after pull request, it's applied to the pull request)
- LDAP StartTLS support
- Enable hard wrapping in Markdown
- Add new some options to specify the data directory. See details in [Wiki](https://github.com/takezoe/gitbucket/wiki/DirectoryStructure).
- Fix some bugs
### 1.7 - 26 Oct 2013
- Support working on Java6 in embedded Jetty mode
- Add `--host` option to bind specified host name in embedded Jetty mode
- Add `--https=true` option to force https scheme when using embedded Jetty mode at the back of https proxy
- Add full name as user property
- Change link color for absent Wiki pages
- Add ZIP download button to the repository viewer tab
- Improve ZIP exporting performance
- Expand issue and comment textarea for long text automatically
- Add conflict detection in Wiki
- Add reverting wiki page from history
- Match committer to user name by email address
- Mail notification sender is customizable
- Add link to changeset in refs comment for issues
- Fix some bugs
### 1.6 - 1 Oct 2013
- Web hook
- Performance improvement for pull request
- Executable war file
- Specify suitable Content-Type for downloaded files in the repository viewer
- Fix some bugs
### 1.5 - 4 Sep 2013
- Fork and pull request
- LDAP authentication
- Mail notification
- Add an option to turn off the gravatar support
- Add the branch tab in the repository viewer
- Encoding auto detection for the file content in the repository viewer
- Add favicon, header logo and icons for the timeline
- Specify data directory via environment variable GITBUCKET_HOME
- Fix some bugs
### 1.4 - 31 Jul 2013
- Group management
- Repository search for code and issues
- Display user related issues on the dashboard
- Display participants avatar of issues on the issue page
- Performance improvement for repository viewer
- Alert by milestone due date
- H2 database administration console
- Fix some bugs
### 1.3 - 18 Jul 2013
- Batch updating for issues
- Display assigned user on issue list
- User icon and Gravatar support
- Convert @xxxx to link to the account page
- Add copy to clipboard button for git clone URL
- Allow multi-byte characters as wiki page name
- Allow to create the empty repository
- Fix some bugs
### 1.2 - 09 Jul 2013
- Add activity timeline
- Bugfix for Git 1.8.1.5 or later
- Allow multi-byte characters as label
- Fix some bugs
### 1.1 - 05 Jul 2013
- Fix some bugs
- Upgrade to JGit 3.0
### 1.0 - 04 Jul 2013
- This is a first public release
See the [change log](CHANGELOG.md) for all of the updates.

View File

@@ -1,16 +1,21 @@
import com.typesafe.sbt.license.{LicenseInfo, DepModuleInfo}
import com.typesafe.sbt.pgp.PgpKeys._
val Organization = "io.github.gitbucket"
val Name = "gitbucket"
val GitBucketVersion = "4.17.0"
val ScalatraVersion = "2.5.0"
val JettyVersion = "9.3.19.v20170502"
val GitBucketVersion = "4.19.2"
val ScalatraVersion = "2.6.1"
val JettyVersion = "9.4.7.v20170914"
lazy val root = (project in file(".")).enablePlugins(SbtTwirl, JettyPlugin)
lazy val root = (project in file(".")).enablePlugins(SbtTwirl, ScalatraPlugin, JRebelPlugin).settings(
)
sourcesInBase := false
organization := Organization
name := Name
version := GitBucketVersion
scalaVersion := "2.12.3"
scalaVersion := "2.12.4"
// dependency settings
resolvers ++= Seq(
@@ -21,12 +26,12 @@ resolvers ++= Seq(
"amateras-snapshot" at "http://amateras.sourceforge.jp/mvn-snapshot/"
)
libraryDependencies ++= Seq(
"org.eclipse.jgit" % "org.eclipse.jgit.http.server" % "4.8.0.201706111038-r",
"org.eclipse.jgit" % "org.eclipse.jgit.archive" % "4.8.0.201706111038-r",
"org.eclipse.jgit" % "org.eclipse.jgit.http.server" % "4.9.0.201710071750-r",
"org.eclipse.jgit" % "org.eclipse.jgit.archive" % "4.9.0.201710071750-r",
"org.scalatra" %% "scalatra" % ScalatraVersion,
"org.scalatra" %% "scalatra-json" % ScalatraVersion,
"org.scalatra" %% "scalatra-forms" % ScalatraVersion,
"org.json4s" %% "json4s-jackson" % "3.5.1",
"io.github.gitbucket" %% "scalatra-forms" % "1.1.0",
"commons-io" % "commons-io" % "2.5",
"io.github.gitbucket" % "solidbase" % "1.0.2",
"io.github.gitbucket" % "markedj" % "1.0.15",
@@ -36,10 +41,9 @@ libraryDependencies ++= Seq(
"org.apache.sshd" % "apache-sshd" % "1.4.0" exclude("org.slf4j","slf4j-jdk14"),
"org.apache.tika" % "tika-core" % "1.14",
"com.github.takezoe" %% "blocking-slick-32" % "0.0.10",
"joda-time" % "joda-time" % "2.9.9",
"com.novell.ldap" % "jldap" % "2009-10-07",
"com.h2database" % "h2" % "1.4.195",
"org.mariadb.jdbc" % "mariadb-java-client" % "2.0.3",
"org.mariadb.jdbc" % "mariadb-java-client" % "2.1.2",
"org.postgresql" % "postgresql" % "42.0.0",
"ch.qos.logback" % "logback-classic" % "1.2.3",
"com.zaxxer" % "HikariCP" % "2.6.1",
@@ -87,17 +91,22 @@ assemblyMergeStrategy in assembly := {
}
// JRebel
Seq(jrebelSettings: _*)
//Seq(jrebelSettings: _*)
jrebel.webLinks += (target in webappPrepare).value
jrebel.enabled := System.getenv().get("JREBEL") != null
//jrebel.webLinks += (target in webappPrepare).value
//jrebel.enabled := System.getenv().get("JREBEL") != null
javaOptions in Jetty ++= Option(System.getenv().get("JREBEL")).toSeq.flatMap { path =>
Seq("-noverify", "-XX:+UseConcMarkSweepGC", "-XX:+CMSClassUnloadingEnabled", s"-javaagent:${path}")
Seq("-noverify", "-XX:+UseConcMarkSweepGC", "-XX:+CMSClassUnloadingEnabled", s"-javaagent:${path}")
}
// Exclude a war file from published artifacts
signedArtifacts := {
signedArtifacts.value.filterNot { case (_, file) => file.getName.endsWith(".war") || file.getName.endsWith(".war.asc") }
}
// Create executable war file
val executableConfig = config("executable").hide
Keys.ivyConfigurations += executableConfig
val ExecutableConfig = config("executable").hide
Keys.ivyConfigurations += ExecutableConfig
libraryDependencies ++= Seq(
"org.eclipse.jetty" % "jetty-security" % JettyVersion % "executable",
"org.eclipse.jetty" % "jetty-webapp" % JettyVersion % "executable",
@@ -126,7 +135,7 @@ executableKey := {
IO delete temp
// include jetty classes
val jettyJars = Keys.update.value select configurationFilter(name = executableConfig.name)
val jettyJars = Keys.update.value select configurationFilter(name = ExecutableConfig.name)
jettyJars foreach { jar =>
IO unzip (jar, temp, (name:String) =>
(name startsWith "javax/") ||
@@ -151,24 +160,20 @@ executableKey := {
IO copyFile(Keys.baseDirectory.value / "plugins.json", pluginsDir / "plugins.json")
val json = IO read(Keys.baseDirectory.value / "plugins.json")
PluginsJson.parse(json).foreach { case (plugin, version) =>
val url = if(plugin == "gitbucket-pages-plugin"){
s"https://github.com/gitbucket/${plugin}/releases/download/v${version}/${plugin}_${scalaBinaryVersion.value}-${version}.jar"
} else {
s"https://github.com/gitbucket/${plugin}/releases/download/${version}/${plugin}_${scalaBinaryVersion.value}-${version}.jar"
}
PluginsJson.parse(json).foreach { case (plugin, version, file) =>
val url = s"https://github.com/gitbucket/${plugin}/releases/download/${version}/${file}"
log info s"Download: ${url}"
IO download(new java.net.URL(url), pluginsDir / s"${plugin}_${scalaBinaryVersion.value}-${version}.jar")
IO transfer(new java.net.URL(url).openStream, pluginsDir / file)
}
// zip it up
IO delete (temp / "META-INF" / "MANIFEST.MF")
val contentMappings = (temp.*** --- PathFinder(temp)).get pair relativeTo(temp)
val contentMappings = (temp.allPaths --- PathFinder(temp)).get pair { file => IO.relativizeFile(temp, file) }
val manifest = new JarManifest
manifest.getMainAttributes put (AttrName.MANIFEST_VERSION, "1.0")
manifest.getMainAttributes put (AttrName.MAIN_CLASS, "JettyLauncher")
val outputFile = workDir / warName
IO jar (contentMappings, outputFile, manifest)
IO jar (contentMappings.map { case (file, path) => (file, path.toString) } , outputFile, manifest)
// generate checksums
Seq(
@@ -188,7 +193,7 @@ executableKey := {
publishTo := {
val nexus = "https://oss.sonatype.org/"
if (version.value.trim.endsWith("SNAPSHOT")) Some("snapshots" at nexus + "content/repositories/snapshots")
else Some("releases" at nexus + "service/local/staging/deploy/maven2")
else Some("releases" at nexus + "service/local/staging/deploy/maven2")
}
publishMavenStyle := true
pomIncludeRepository := { _ => false }
@@ -237,3 +242,8 @@ pomExtra := (
</developer>
</developers>
)
licenseOverrides := {
case DepModuleInfo("com.github.bkromhout", "java-diff-utils", _) =>
LicenseInfo(LicenseCategory.Apache, "Apache-2.0", "http://www.apache.org/licenses/LICENSE-2.0")
}

101
doc/licenses.md Normal file
View File

@@ -0,0 +1,101 @@
# gitbucket-licenses
Category | License | Dependency | Notes
--- | --- | --- | ---
Apache | [ Apache License, Version 2.0 ]( http://opensource.org/licenses/apache2.0.php ) | org.osgi # org.osgi.core # 4.3.1 | <notextile></notextile>
Apache | [Apache 2](http://www.apache.org/licenses/LICENSE-2.0.txt) | com.googlecode.javaewah # JavaEWAH # 1.1.6 | <notextile></notextile>
Apache | [Apache 2](http://www.apache.org/licenses/LICENSE-2.0) | org.cache2k # cache2k-all # 1.0.0.CR1 | <notextile></notextile>
Apache | [Apache 2](http://www.apache.org/licenses/LICENSE-2.0.txt) | org.objenesis # objenesis # 2.5 | <notextile></notextile>
Apache | [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0) | org.apache.sshd # apache-sshd # 1.4.0 | <notextile></notextile>
Apache | [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0) | org.apache.sshd # sshd-core # 1.4.0 | <notextile></notextile>
Apache | [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) | com.typesafe # config # 1.3.1 | <notextile></notextile>
Apache | [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) | com.typesafe.akka # akka-actor_2.12 # 2.5.0 | <notextile></notextile>
Apache | [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | commons-io # commons-io # 2.5 | <notextile></notextile>
Apache | [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | fr.brouillard.oss.security.xhub # xhub4j-core # 1.0.0 | <notextile></notextile>
Apache | [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt) | org.apache.commons # commons-compress # 1.13 | <notextile></notextile>
Apache | [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | org.apache.commons # commons-email # 1.4 | <notextile></notextile>
Apache | [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.txt) | org.apache.commons # commons-lang3 # 3.5 | <notextile></notextile>
Apache | [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | org.apache.httpcomponents # httpclient # 4.5.3 | <notextile></notextile>
Apache | [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | org.apache.httpcomponents # httpcore # 4.4.6 | <notextile></notextile>
Apache | [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | org.apache.httpcomponents # httpmime # 4.5.2 | <notextile></notextile>
Apache | [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | org.apache.tika # tika-core # 1.14 | <notextile></notextile>
Apache | [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) | org.liquibase # liquibase-core # 3.4.1 | <notextile></notextile>
Apache | [Apache Software License - Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) | org.eclipse.jetty # jetty-http # 9.2.19.v20160908 | <notextile></notextile>
Apache | [Apache Software License - Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) | org.eclipse.jetty # jetty-io # 9.2.19.v20160908 | <notextile></notextile>
Apache | [Apache Software License - Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) | org.eclipse.jetty # jetty-security # 9.2.19.v20160908 | <notextile></notextile>
Apache | [Apache Software License - Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) | org.eclipse.jetty # jetty-server # 9.2.19.v20160908 | <notextile></notextile>
Apache | [Apache Software License - Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) | org.eclipse.jetty # jetty-servlet # 9.2.19.v20160908 | <notextile></notextile>
Apache | [Apache Software License - Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) | org.eclipse.jetty # jetty-util # 9.2.19.v20160908 | <notextile></notextile>
Apache | [Apache Software License - Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) | org.eclipse.jetty # jetty-webapp # 9.2.19.v20160908 | <notextile></notextile>
Apache | [Apache Software License - Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) | org.eclipse.jetty # jetty-xml # 9.2.19.v20160908 | <notextile></notextile>
Apache | [Apache Software License, Version 1.1](http://www.apache.org/licenses/LICENSE-1.1) | org.bouncycastle # bcpg-jdk15on # 1.56 | <notextile></notextile>
Apache | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | com.github.bkromhout # java-diff-utils # 2.1.1 | <notextile></notextile>
Apache | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0.html) | com.typesafe.play # twirl-api_2.12 # 1.3.7 | <notextile></notextile>
Apache | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | org.json4s # json4s-ast_2.12 # 3.5.1 | <notextile></notextile>
Apache | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | org.json4s # json4s-core_2.12 # 3.5.1 | <notextile></notextile>
Apache | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | org.json4s # json4s-jackson_2.12 # 3.5.1 | <notextile></notextile>
Apache | [Apache-2.0](http://www.apache.org/licenses/LICENSE-2.0) | org.json4s # json4s-scalap_2.12 # 3.5.1 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | com.enragedginger # akka-quartz-scheduler_2.12 # 1.6.0-akka-2.4.x | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | com.fasterxml.jackson.core # jackson-annotations # 2.8.0 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | com.fasterxml.jackson.core # jackson-core # 2.8.4 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | com.fasterxml.jackson.core # jackson-databind # 2.8.4 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | com.github.takezoe # blocking-slick-32_2.12 # 0.0.10 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | com.google.code.findbugs # jsr305 # 3.0.0 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | com.zaxxer # HikariCP # 2.6.1 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | commons-codec # commons-codec # 1.9 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | commons-logging # commons-logging # 1.2 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | de.flapdoodle.embed # de.flapdoodle.embed.process # 2.0.1 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | eu.medsea.mimeutil # mime-util # 2.1.3 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | io.github.gitbucket # markedj # 1.0.15 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | io.github.gitbucket # scalatra-forms_2.12 # 1.1.0 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | io.github.gitbucket # solidbase # 1.0.2 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | net.bytebuddy # byte-buddy # 1.6.11 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | net.bytebuddy # byte-buddy-agent # 1.6.11 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | org.quartz-scheduler # quartz # 2.2.3 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | ru.yandex.qatools.embed # postgresql-embedded # 2.0 | <notextile></notextile>
Apache | [The Apache Software License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.txt) | tomcat # tomcat-apr # 5.5.23 | <notextile></notextile>
Apache | [the Apache License, ASL Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) | org.scalactic # scalactic_2.12 # 3.0.0 | <notextile></notextile>
Apache | [the Apache License, ASL Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) | org.scalatest # scalatest_2.12 # 3.0.0 | <notextile></notextile>
BSD | [BSD](LICENSE.txt) | com.thoughtworks.paranamer # paranamer # 2.8 | <notextile></notextile>
BSD | [BSD](http://software.clapper.org/grizzled-slf4j/license.html) | org.clapper # grizzled-slf4j_2.12 # 1.3.0 | <notextile></notextile>
BSD | [BSD](http://github.com/scalatra/scalatra/raw/HEAD/LICENSE) | org.scalatra # scalatra-common_2.12 # 2.5.0 | <notextile></notextile>
BSD | [BSD](http://github.com/scalatra/scalatra/raw/HEAD/LICENSE) | org.scalatra # scalatra-json_2.12 # 2.5.0 | <notextile></notextile>
BSD | [BSD](http://github.com/scalatra/scalatra/raw/HEAD/LICENSE) | org.scalatra # scalatra-scalatest_2.12 # 2.5.0 | <notextile></notextile>
BSD | [BSD](http://github.com/scalatra/scalatra/raw/HEAD/LICENSE) | org.scalatra # scalatra-test_2.12 # 2.5.0 | <notextile></notextile>
BSD | [BSD](http://github.com/scalatra/scalatra/raw/HEAD/LICENSE) | org.scalatra # scalatra_2.12 # 2.5.0 | <notextile></notextile>
BSD | [BSD 3-Clause](http://www.scala-lang.org/license.html) | org.scala-lang # scala-library # 2.12.3 | <notextile></notextile>
BSD | [BSD 3-Clause](http://www.scala-lang.org/license.html) | org.scala-lang # scala-reflect # 2.12.3 | <notextile></notextile>
BSD | [BSD 3-clause](http://opensource.org/licenses/BSD-3-Clause) | org.scala-lang.modules # scala-java8-compat_2.12 # 0.8.0 | <notextile></notextile>
BSD | [BSD 3-clause](http://opensource.org/licenses/BSD-3-Clause) | org.scala-lang.modules # scala-parser-combinators_2.12 # 1.0.4 | <notextile></notextile>
BSD | [BSD 3-clause](http://opensource.org/licenses/BSD-3-Clause) | org.scala-lang.modules # scala-xml_2.12 # 1.0.6 | <notextile></notextile>
BSD | [BSD License](http://www.opensource.org/licenses/bsd-license.php) | com.wix # wix-embedded-mysql # 2.1.4 | <notextile></notextile>
BSD | [BSD-2-Clause](https://jdbc.postgresql.org/about/license.html) | org.postgresql # postgresql # 42.0.0 | <notextile></notextile>
BSD | [Eclipse Distribution License (New BSD License)](null) | org.eclipse.jgit # org.eclipse.jgit # 4.8.0.201706111038-r | <notextile></notextile>
BSD | [Eclipse Distribution License (New BSD License)](null) | org.eclipse.jgit # org.eclipse.jgit.archive # 4.8.0.201706111038-r | <notextile></notextile>
BSD | [Eclipse Distribution License (New BSD License)](null) | org.eclipse.jgit # org.eclipse.jgit.http.server # 4.8.0.201706111038-r | <notextile></notextile>
BSD | [New BSD License](http://www.opensource.org/licenses/bsd-license.php) | org.hamcrest # hamcrest-core # 1.3 | <notextile></notextile>
BSD | [Revised BSD](http://www.jcraft.com/jsch/LICENSE.txt) | com.jcraft # jsch # 0.1.54 | <notextile></notextile>
BSD | [Two-clause BSD-style license](http://github.com/slick/slick/blob/master/LICENSE.txt) | com.typesafe.slick # slick_2.12 # 3.2.1 | <notextile></notextile>
CC0 | [CC0](http://creativecommons.org/publicdomain/zero/1.0/) | org.reactivestreams # reactive-streams # 1.0.0 | <notextile></notextile>
CDDL | [COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0](https://glassfish.dev.java.net/public/CDDLv1.0.html) | javax.activation # activation # 1.1.1 | <notextile></notextile>
GPL | [CDDL/GPLv2+CE](https://glassfish.java.net/public/CDDL+GPL_1_1.html) | com.sun.mail # javax.mail # 1.5.2 | <notextile></notextile>
GPL with Classpath Extension | [CDDL + GPLv2 with classpath exception](https://glassfish.dev.java.net/nonav/public/CDDL+GPL.html) | javax.servlet # javax.servlet-api # 3.1.0 | <notextile></notextile>
LGPL | [GNU Lesser General Public License](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) | ch.qos.logback # logback-classic # 1.2.3 | <notextile></notextile>
LGPL | [GNU Lesser General Public License](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) | ch.qos.logback # logback-core # 1.2.3 | <notextile></notextile>
LGPL | [LGPL, version 2.1](http://www.gnu.org/licenses/licenses.html) | net.java.dev.jna # jna # 4.0.0 | <notextile></notextile>
LGPL | [LGPL, version 2.1](http://www.gnu.org/licenses/licenses.html) | net.java.dev.jna # jna-platform # 4.0.0 | <notextile></notextile>
LGPL | [LGPL-2.1](null) | org.mariadb.jdbc # mariadb-java-client # 2.0.3 | <notextile></notextile>
MIT | [MIT License](http://www.opensource.org/licenses/mit-license.php) | org.slf4j # slf4j-api # 1.7.25 | <notextile></notextile>
MIT | [The MIT License](http://www.opensource.org/licenses/mit-license.php) | com.github.zafarkhaja # java-semver # 0.9.0 | <notextile></notextile>
MIT | [The MIT License](https://jsoup.org/license) | org.jsoup # jsoup # 1.10.2 | <notextile></notextile>
MIT | [The MIT License](http://github.com/mockito/mockito/blob/master/LICENSE) | org.mockito # mockito-all # 1.10.19 | <notextile></notextile>
MIT | [The MIT License](http://github.com/mockito/mockito/blob/master/LICENSE) | org.mockito # mockito-core # 2.7.22 | <notextile></notextile>
MIT | [The MIT License (MIT)](http://www.opensource.org/licenses/mit-license.html) | net.coobird # thumbnailator # 0.4.8 | <notextile></notextile>
Mozilla | [MPL 2.0 or EPL 1.0](http://h2database.com/html/license.html) | com.h2database # h2 # 1.4.195 | <notextile></notextile>
Mozilla | [Mozilla Public License 1.1 (MPL 1.1)](http://www.mozilla.org/MPL/MPL-1.1.html) | com.googlecode.juniversalchardet # juniversalchardet # 1.0.3 | <notextile></notextile>
Public Domain | [Public Domain](http://en.wikipedia.org/wiki/Public_domain) | net.i2p.crypto # eddsa # 0.1.0 | <notextile></notextile>
unrecognized | [Bouncy Castle Licence](http://www.bouncycastle.org/licence.html) | org.bouncycastle # bcpkix-jdk15on # 1.56 | <notextile></notextile>
unrecognized | [Bouncy Castle Licence](http://www.bouncycastle.org/licence.html) | org.bouncycastle # bcprov-jdk15on # 1.56 | <notextile></notextile>
unrecognized | [Eclipse Public License 1.0](http://www.eclipse.org/legal/epl-v10.html) | junit # junit # 4.12 | <notextile></notextile>
unrecognized | [The OpenLDAP Public License](http://www.openldap.org/software/release/license.html) | com.novell.ldap # jldap # 2009-10-07 | <notextile></notextile>

View File

@@ -9,3 +9,4 @@ Developer's Guide
* [Automatic Schema Updating](auto_update.md)
* [Release Operation](release.md)
* [JRebel integration (optional)](jrebel.md)
* [Licenses](licenses.md)

View File

@@ -5,9 +5,9 @@
"description": "Provides notifications feature on GitBucket.",
"versions": [
{
"version": "1.2.0",
"range": ">=4.17.0",
"file": "gitbucket-notifications-plugin_2.12-1.2.0.jar"
"version": "1.4.0",
"range": ">=4.19.0",
"file": "gitbucket-notifications-plugin_2.12-1.4.0.jar"
}
],
"default": true
@@ -18,9 +18,9 @@
"description": "Provides Emoji support for GitBucket.",
"versions": [
{
"version": "4.4.0",
"range": ">=4.10.0",
"file": "gitbucket-emoji-plugin_2.12-4.4.0.jar"
"version": "4.5.0",
"range": ">=4.18.0",
"file": "gitbucket-emoji-plugin_2.12-4.5.0.jar"
}
],
"default": false
@@ -31,22 +31,9 @@
"description": "Provides Gist feature on GitBucket.",
"versions": [
{
"version": "4.10.0",
"range": ">=4.15.0",
"file": "gitbucket-gist-plugin_2.12-4.10.0.jar"
}
],
"default": false
},
{
"id": "pages",
"name": "Pages Plugin",
"description": "Project pages for gitbucket",
"versions": [
{
"version": "1.5.0",
"range": ">=4.15.0",
"file": "gitbucket-pages-plugin_2.12-1.5.0.jar"
"version": "4.11.0",
"range": ">=4.19.0",
"file": "gitbucket-gist-plugin-assembly-4.11.0.jar"
}
],
"default": false

View File

@@ -1,12 +1,13 @@
import java.security.MessageDigest
import scala.annotation._
import sbt._
import io._
object Checksums {
private val bufferSize = 2048
def generate(source:File, target:File, algorithm:String):Unit =
IO write (target, compute(source, algorithm))
sbt.IO write (target, compute(source, algorithm))
def compute(file:File, algorithm:String):String =
hex(raw(file, algorithm))

View File

@@ -3,13 +3,17 @@ import scala.collection.JavaConverters._
object PluginsJson {
def parse(json: String): Seq[(String, String)] = {
def parse(json: String): Seq[(String, String, String)] = {
val value = Json.parse(json)
value.asArray.values.asScala.map { plugin =>
val obj = plugin.asObject.get("versions").asArray.asScala.head.asObject
val pluginName = obj.get("file").asString.split("_2.12-").head
val version = obj.get("version").asString
(pluginName, version)
val pluginObject = plugin.asObject
val pluginName = "gitbucket-" + pluginObject.get("id").asString + "-plugin"
val latestVersionObject = pluginObject.get("versions").asArray.asScala.head.asObject
val file = latestVersionObject.get("file").asString
val version = latestVersionObject.get("version").asString
(pluginName, version, file)
}
}

View File

@@ -1 +1 @@
sbt.version=0.13.15
sbt.version=1.0.4

View File

@@ -1,8 +1,10 @@
scalacOptions ++= Seq("-unchecked", "-deprecation", "-feature")
addSbtPlugin("com.typesafe.sbt" % "sbt-twirl" % "1.3.7")
addSbtPlugin("com.typesafe.sbt" % "sbt-twirl" % "1.3.12")
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.5")
addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "4.0.0")
addSbtPlugin("fi.gekkio.sbtplugins" % "sbt-jrebel-plugin" % "0.10.0")
//addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "4.0.0")
//addSbtPlugin("fi.gekkio.sbtplugins" % "sbt-jrebel-plugin" % "0.10.0")
addSbtPlugin("org.scalatra.sbt" % "sbt-scalatra" % "1.0.1")
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0")
addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC11")
addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC13")
addSbtPlugin("com.typesafe.sbt" % "sbt-license-report" % "1.2.0")

View File

@@ -1 +1 @@
addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-M15")
addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC11")

View File

@@ -32,20 +32,25 @@ class ScalatraBootstrap extends LifeCycle with SystemSettingsService {
context.addFilter("pluginControllerFilter", new PluginControllerFilter)
context.getFilterRegistration("pluginControllerFilter").addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/*")
context.mount(new IndexController, "/")
context.mount(new ApiController, "/api/v3")
context.mount(new FileUploadController, "/upload")
context.mount(new SystemSettingsController, "/admin")
context.mount(new DashboardController, "/*")
context.mount(new AccountController, "/*")
context.mount(new RepositoryViewerController, "/*")
context.mount(new WikiController, "/*")
context.mount(new LabelsController, "/*")
context.mount(new PrioritiesController, "/*")
context.mount(new MilestonesController, "/*")
context.mount(new IssuesController, "/*")
context.mount(new PullRequestsController, "/*")
context.mount(new RepositorySettingsController, "/*")
val filter = new CompositeScalatraFilter()
filter.mount(new IndexController, "/")
filter.mount(new ApiController, "/api/v3")
filter.mount(new SystemSettingsController, "/admin")
filter.mount(new DashboardController, "/*")
filter.mount(new AccountController, "/*")
filter.mount(new RepositoryViewerController, "/*")
filter.mount(new WikiController, "/*")
filter.mount(new LabelsController, "/*")
filter.mount(new PrioritiesController, "/*")
filter.mount(new MilestonesController, "/*")
filter.mount(new IssuesController, "/*")
filter.mount(new PullRequestsController, "/*")
filter.mount(new RepositorySettingsController, "/*")
context.addFilter("compositeScalatraFilter", filter)
context.getFilterRegistration("compositeScalatraFilter").addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/*")
// Create GITBUCKET_HOME directory if it does not exist
val dir = new java.io.File(Directory.GitBucketHome)

View File

@@ -42,5 +42,9 @@ object GitBucketCoreModule extends Module("gitbucket-core",
new Version("4.14.1"),
new Version("4.15.0"),
new Version("4.16.0"),
new Version("4.17.0")
new Version("4.17.0"),
new Version("4.18.0"),
new Version("4.19.0"),
new Version("4.19.1"),
new Version("4.19.2")
)

View File

@@ -1,23 +1,24 @@
package gitbucket.core.api
import org.joda.time.DateTime
import org.joda.time.DateTimeZone
import org.joda.time.format._
import java.time._
import java.time.format.DateTimeFormatter
import java.util.Date
import scala.util.Try
import org.json4s._
import org.json4s.jackson.Serialization
import java.util.Date
import scala.util.Try
object JsonFormat {
case class Context(baseUrl: String, sshUrl: Option[String])
val parserISO = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")
val parserISO = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")
val jsonFormats = Serialization.formats(NoTypeHints) + new CustomSerializer[Date](format =>
(
{ case JString(s) => Try(parserISO.parseDateTime(s)).toOption.map(_.toDate).getOrElse(throw new MappingException("Can't convert " + s + " to Date")) },
{ case x: Date => JString(parserISO.print(new DateTime(x).withZone(DateTimeZone.UTC))) }
{ case JString(s) => Try(Date.from(Instant.parse(s))).getOrElse(throw new MappingException("Can't convert " + s + " to Date")) },
{ case x: Date => JString(OffsetDateTime.ofInstant(x.toInstant, ZoneId.of("UTC")).format(parserISO)) }
)
) + FieldSerializer[ApiUser]() +
FieldSerializer[ApiPullRequest]() +

View File

@@ -12,10 +12,10 @@ import gitbucket.core.util.Directory._
import gitbucket.core.util.Implicits._
import gitbucket.core.util.StringUtil._
import gitbucket.core.util._
import io.github.gitbucket.scalatra.forms._
import org.apache.commons.io.FileUtils
import org.scalatra.i18n.Messages
import org.scalatra.BadRequest
import org.scalatra.forms._
class AccountController extends AccountControllerBase
with AccountService with RepositoryService with ActivityService with WikiService with LabelsService with SshKeyService
@@ -137,16 +137,17 @@ trait AccountControllerBase extends AccountManagementControllerBase {
}
private def accountWebhookEvents = new ValueType[Set[WebHook.Event]]{
def convert(name: String, params: Map[String, String], messages: Messages): Set[WebHook.Event] = {
def convert(name: String, params: Map[String, Seq[String]], messages: Messages): Set[WebHook.Event] = {
WebHook.Event.values.flatMap { t =>
params.get(name + "." + t.name).map(_ => t)
params.optionValue(name + "." + t.name).map(_ => t)
}.toSet
}
def validate(name: String, params: Map[String, String], messages: Messages): Seq[(String, String)] = if(convert(name,params,messages).isEmpty){
Seq(name -> messages("error.required").format(name))
} else {
Nil
}
def validate(name: String, params: Map[String, Seq[String]], messages: Messages): Seq[(String, String)] =
if(convert(name, params, messages).isEmpty){
Seq(name -> messages("error.required").format(name))
} else {
Nil
}
}
@@ -635,10 +636,14 @@ trait AccountControllerBase extends AccountManagementControllerBase {
}
private def uniqueRepository: Constraint = new Constraint(){
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Option[String] =
params.get("owner").flatMap { userName =>
getRepositoryNamesOfUser(userName).find(_ == value).map(_ => "Repository already exists.")
override def validate(name: String, value: String, params: Map[String, Seq[String]], messages: Messages): Option[String] = {
for {
userName <- params.optionValue("owner")
_ <- getRepositoryNamesOfUser(userName).find(_ == value)
} yield {
"Repository already exists."
}
}
}
private def members: Constraint = new Constraint(){

View File

@@ -9,12 +9,11 @@ import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.Directory._
import gitbucket.core.util.Implicits._
import gitbucket.core.util._
import gitbucket.core.util.JGitUtil._
import io.github.gitbucket.scalatra.forms._
import org.json4s._
import org.scalatra._
import org.scalatra.i18n._
import org.scalatra.json._
import org.scalatra.forms._
import javax.servlet.http.{HttpServletRequest, HttpServletResponse}
import javax.servlet.{FilterChain, ServletRequest, ServletResponse}
@@ -32,7 +31,7 @@ import org.slf4j.LoggerFactory
* Provides generic features for controller implementations.
*/
abstract class ControllerBase extends ScalatraFilter
with ClientSideValidationFormSupport with JacksonJsonSupport with I18nSupport with FlashMapSupport with Validations
with ValidationSupport with JacksonJsonSupport with I18nSupport with FlashMapSupport with Validations
with SystemSettingsService {
private val logger = LoggerFactory.getLogger(getClass)
@@ -177,7 +176,7 @@ abstract class ControllerBase extends ScalatraFilter
protected def trim2[T](valueType: SingleValueType[T]): SingleValueType[T] = new SingleValueType[T](){
def convert(value: String, messages: Messages): T = valueType.convert(trim(value), messages)
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Seq[(String, String)] =
override def validate(name: String, value: String, params: Map[String, Seq[String]], messages: Messages): Seq[(String, String)] =
valueType.validate(name, trim(value), params, messages)
private def trim(value: String): String = if(value == null) null else value.replace("\r\n", "").trim
@@ -315,13 +314,14 @@ trait AccountManagementControllerBase extends ControllerBase {
}
protected def uniqueMailAddress(paramName: String = ""): Constraint = new Constraint(){
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Option[String] =
override def validate(name: String, value: String, params: Map[String, Seq[String]], messages: Messages): Option[String] = {
getAccountByMailAddress(value, true)
.filter { x => if(paramName.isEmpty) true else Some(x.userName) != params.get(paramName) }
.filter { x => if(paramName.isEmpty) true else Some(x.userName) != params.optionValue(paramName) }
.map { _ => "Mail address is already registered." }
}
}
val allReservedNames = Set("git", "admin", "upload", "api")
val allReservedNames = Set("git", "admin", "upload", "api", "assets", "plugin-assets", "signin", "signout", "register", "activities.atom", "sidebar-collapse", "groups", "new")
protected def reservedNames(): Constraint = new Constraint(){
override def validate(name: String, value: String, messages: Messages): Option[String] = if(allReservedNames.contains(value)){
Some(s"${value} is reserved")

View File

@@ -1,7 +1,6 @@
package gitbucket.core.controller
import gitbucket.core.model.Account
import gitbucket.core.service.RepositoryService.RepositoryInfo
import gitbucket.core.service.{AccountService, RepositoryService}
import gitbucket.core.servlet.Database
import gitbucket.core.util._
@@ -80,7 +79,7 @@ class FileUploadController extends ScalatraServlet with FileUploadSupport with R
builder.finish()
val newHeadId = JGitUtil.createNewCommit(git, inserter, headId, builder.getDirCache.writeTree(inserter),
Constants.HEAD, loginAccount.userName, loginAccount.mailAddress, s"Uploaded ${fileName}")
Constants.HEAD, loginAccount.fullName, loginAccount.mailAddress, s"Uploaded ${fileName}")
fileName
}

View File

@@ -6,7 +6,7 @@ import gitbucket.core.service._
import gitbucket.core.util.Implicits._
import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.{Keys, LDAPUtil, ReferrerAuthenticator, UsersAuthenticator}
import io.github.gitbucket.scalatra.forms._
import org.scalatra.forms._
import org.scalatra.Ok
@@ -75,7 +75,7 @@ trait IndexControllerBase extends ControllerBase {
xml.feed(getRecentActivities())
}
get("/sidebar-collapse"){
post("/sidebar-collapse"){
if(params("collapse") == "true"){
session.setAttribute("sidebar-collapse", "true")
} else {
@@ -121,7 +121,12 @@ trait IndexControllerBase extends ControllerBase {
case (true, false) => !t.isGroupAccount
case (false, true) => t.isGroupAccount
case (false, false) => false
}}.map { t => t.userName }
}}.map { t =>
Map(
"label" -> s"<b>@${t.userName}</b> ${t.fullName}",
"value" -> t.userName
)
}
))
)
})

View File

@@ -8,7 +8,7 @@ import gitbucket.core.util.Implicits._
import gitbucket.core.util._
import gitbucket.core.view
import gitbucket.core.view.Markdown
import io.github.gitbucket.scalatra.forms._
import org.scalatra.forms._
import org.scalatra.{BadRequest, Ok}

View File

@@ -4,7 +4,8 @@ import gitbucket.core.issues.labels.html
import gitbucket.core.service.{RepositoryService, AccountService, IssuesService, LabelsService}
import gitbucket.core.util.{ReferrerAuthenticator, WritableUsersAuthenticator}
import gitbucket.core.util.Implicits._
import io.github.gitbucket.scalatra.forms._
import gitbucket.core.util.SyntaxSugars._
import org.scalatra.forms._
import org.scalatra.i18n.Messages
import org.scalatra.Ok
@@ -82,10 +83,10 @@ trait LabelsControllerBase extends ControllerBase {
}
private def uniqueLabelName: Constraint = new Constraint(){
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Option[String] = {
val owner = params("owner")
val repository = params("repository")
params.get("labelId").map { labelId =>
override def validate(name: String, value: String, params: Map[String, Seq[String]], messages: Messages): Option[String] = {
val owner = params.value("owner")
val repository = params.value("repository")
params.optionValue("labelId").map { labelId =>
getLabel(owner, repository, value).filter(_.labelId != labelId.toInt).map(_ => "Name has already been taken.")
}.getOrElse {
getLabel(owner, repository, value).map(_ => "Name has already been taken.")

View File

@@ -4,7 +4,7 @@ import gitbucket.core.issues.milestones.html
import gitbucket.core.service.{RepositoryService, MilestonesService, AccountService}
import gitbucket.core.util.{ReferrerAuthenticator, WritableUsersAuthenticator}
import gitbucket.core.util.Implicits._
import io.github.gitbucket.scalatra.forms._
import org.scalatra.forms._
class MilestonesController extends MilestonesControllerBase
with MilestonesService with RepositoryService with AccountService

View File

@@ -4,7 +4,8 @@ import gitbucket.core.issues.priorities.html
import gitbucket.core.service.{RepositoryService, AccountService, IssuesService, PrioritiesService}
import gitbucket.core.util.{ReferrerAuthenticator, WritableUsersAuthenticator}
import gitbucket.core.util.Implicits._
import io.github.gitbucket.scalatra.forms._
import gitbucket.core.util.SyntaxSugars._
import org.scalatra.forms._
import org.scalatra.i18n.Messages
import org.scalatra.Ok
@@ -98,10 +99,10 @@ trait PrioritiesControllerBase extends ControllerBase {
}
private def uniquePriorityName: Constraint = new Constraint(){
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Option[String] = {
val owner = params("owner")
val repository = params("repository")
params.get("priorityId").map { priorityId =>
override def validate(name: String, value: String, params: Map[String, Seq[String]], messages: Messages): Option[String] = {
val owner = params.value("owner")
val repository = params.value("repository")
params.optionValue("priorityId").map { priorityId =>
getPriority(owner, repository, value).filter(_.priorityId != priorityId.toInt).map(_ => "Name has already been taken.")
}.getOrElse {
getPriority(owner, repository, value).map(_ => "Name has already been taken.")

View File

@@ -13,7 +13,7 @@ import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.Directory._
import gitbucket.core.util.Implicits._
import gitbucket.core.util._
import io.github.gitbucket.scalatra.forms._
import org.scalatra.forms._
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.lib.PersonIdent

View File

@@ -1,7 +1,10 @@
package gitbucket.core.controller
import java.time.{LocalDateTime, ZoneId, ZoneOffset}
import java.util.Date
import gitbucket.core.settings.html
import gitbucket.core.model.{WebHook, RepositoryWebHook}
import gitbucket.core.model.{RepositoryWebHook, WebHook}
import gitbucket.core.service._
import gitbucket.core.service.WebHookService._
import gitbucket.core.util._
@@ -9,7 +12,7 @@ import gitbucket.core.util.JGitUtil._
import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.Implicits._
import gitbucket.core.util.Directory._
import io.github.gitbucket.scalatra.forms._
import org.scalatra.forms._
import org.apache.commons.io.FileUtils
import org.scalatra.i18n.Messages
import org.eclipse.jgit.api.Git
@@ -175,7 +178,8 @@ trait RepositorySettingsControllerBase extends ControllerBase {
redirect(s"/${repository.owner}/${repository.name}/settings/branches")
} else {
val protection = ApiBranchProtection(getProtectedBranchInfo(repository.owner, repository.name, branch))
val lastWeeks = getRecentStatuesContexts(repository.owner, repository.name, org.joda.time.LocalDateTime.now.minusWeeks(1).toDate).toSet
val lastWeeks = getRecentStatuesContexts(repository.owner, repository.name,
Date.from(LocalDateTime.now.minusWeeks(1).toInstant(ZoneOffset.of("UTC")))).toSet
val knownContexts = (lastWeeks ++ protection.status.contexts).toSeq.sortBy(identity)
html.branchprotection(repository, branch, protection, knownContexts, flash.get("info"))
}
@@ -343,20 +347,12 @@ trait RepositorySettingsControllerBase extends ControllerBase {
FileUtils.moveDirectory(dir, getWikiRepositoryDir(form.newOwner, repository.name))
}
}
// Move lfs directory
defining(getLfsDir(repository.owner, repository.name)){ dir =>
if(dir.isDirectory()) {
FileUtils.moveDirectory(dir, getLfsDir(form.newOwner, repository.name))
}
}
// Move attached directory
defining(getAttachedDir(repository.owner, repository.name)){ dir =>
// Move files directory
defining(getRepositoryFilesDir(repository.owner, repository.name)){ dir =>
if(dir.isDirectory) {
FileUtils.moveDirectory(dir, getAttachedDir(form.newOwner, repository.name))
FileUtils.moveDirectory(dir, getRepositoryFilesDir(form.newOwner, repository.name))
}
}
// Delete parent directory
FileUtil.deleteDirectoryIfEmpty(getRepositoryFilesDir(repository.owner, repository.name))
// Call hooks
PluginRegistry().getRepositoryHooks.foreach(_.transferred(repository.owner, form.newOwner, repository.name))
@@ -376,9 +372,7 @@ trait RepositorySettingsControllerBase extends ControllerBase {
FileUtils.deleteDirectory(getRepositoryDir(repository.owner, repository.name))
FileUtils.deleteDirectory(getWikiRepositoryDir(repository.owner, repository.name))
FileUtils.deleteDirectory(getTemporaryDir(repository.owner, repository.name))
val lfsDir = getLfsDir(repository.owner, repository.name)
FileUtils.deleteDirectory(lfsDir)
FileUtil.deleteDirectoryIfEmpty(lfsDir.getParentFile())
FileUtils.deleteDirectory(getRepositoryFilesDir(repository.owner, repository.name))
// Call hooks
PluginRegistry().getRepositoryHooks.foreach(_.deleted(repository.owner, repository.name))
@@ -435,12 +429,12 @@ trait RepositorySettingsControllerBase extends ControllerBase {
}
private def webhookEvents = new ValueType[Set[WebHook.Event]]{
def convert(name: String, params: Map[String, String], messages: Messages): Set[WebHook.Event] = {
def convert(name: String, params: Map[String, Seq[String]], messages: Messages): Set[WebHook.Event] = {
WebHook.Event.values.flatMap { t =>
params.get(name + "." + t.name).map(_ => t)
}.toSet
}
def validate(name: String, params: Map[String, String], messages: Messages): Seq[(String, String)] = if(convert(name,params,messages).isEmpty){
def validate(name: String, params: Map[String, Seq[String]], messages: Messages): Seq[(String, String)] = if(convert(name,params,messages).isEmpty){
Seq(name -> messages("error.required").format(name))
} else {
Nil
@@ -466,19 +460,22 @@ trait RepositorySettingsControllerBase extends ControllerBase {
* Duplicate check for the rename repository name.
*/
private def renameRepositoryName: Constraint = new Constraint(){
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Option[String] =
params.get("repository").filter(_ != value).flatMap { _ =>
params.get("owner").flatMap { userName =>
getRepositoryNamesOfUser(userName).find(_ == value).map(_ => "Repository already exists.")
}
override def validate(name: String, value: String, params: Map[String, Seq[String]], messages: Messages): Option[String] = {
for {
repoName <- params.optionValue("repository") if repoName != value
userName <- params.optionValue("owner")
_ <- getRepositoryNamesOfUser(userName).find(_ == value)
} yield {
"Repository already exists."
}
}
}
/**
*
*/
private def featureOption: Constraint = new Constraint(){
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Option[String] =
override def validate(name: String, value: String, params: Map[String, Seq[String]], messages: Messages): Option[String] =
if(Seq("DISABLE", "PRIVATE", "PUBLIC", "ALL").contains(value)) None else Some("Option is invalid.")
}

View File

@@ -17,13 +17,14 @@ import gitbucket.core.model.{Account, CommitState, CommitStatus, WebHook}
import gitbucket.core.service.WebHookService._
import gitbucket.core.view
import gitbucket.core.view.helpers
import io.github.gitbucket.scalatra.forms._
import org.scalatra.forms._
import org.apache.commons.io.FileUtils
import org.eclipse.jgit.api.{ArchiveCommand, Git}
import org.eclipse.jgit.archive.{TgzFormat, ZipFormat}
import org.eclipse.jgit.dircache.{DirCache, DirCacheBuilder}
import org.eclipse.jgit.errors.MissingObjectException
import org.eclipse.jgit.lib._
import org.eclipse.jgit.transport.{ReceiveCommand, ReceivePack}
import org.scalatra._
import org.scalatra.i18n.Messages
@@ -320,7 +321,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
commit = form.commit
)
redirect(s"/${repository.owner}/${repository.name}/blob/${form.branch}/${
redirect(s"/${repository.owner}/${repository.name}/blob/${urlEncode(form.branch)}/${
if (form.path.length == 0) urlEncode(form.newFileName) else s"${form.path}/${urlEncode(form.newFileName)}"
}")
})
@@ -431,7 +432,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
try {
using(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
defining(JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(id))) { revCommit =>
JGitUtil.getDiffs(git, id, false) match {
JGitUtil.getDiffs(git, id, true) match {
case (diffs, oldCommitId) =>
html.commit(id, new JGitUtil.CommitInfo(revCommit),
JGitUtil.getBranchesOfCommit(git, revCommit.getName),
@@ -717,39 +718,63 @@ trait RepositoryViewerControllerBase extends ControllerBase {
f(git, headTip, builder, inserter)
val commitId = JGitUtil.createNewCommit(git, inserter, headTip, builder.getDirCache.writeTree(inserter),
headName, loginAccount.userName, loginAccount.mailAddress, message)
headName, loginAccount.fullName, loginAccount.mailAddress, message)
inserter.flush()
inserter.close()
// update refs
val refUpdate = git.getRepository.updateRef(headName)
refUpdate.setNewObjectId(commitId)
refUpdate.setForceUpdate(false)
refUpdate.setRefLogIdent(new PersonIdent(loginAccount.fullName, loginAccount.mailAddress))
refUpdate.update()
val receivePack = new ReceivePack(git.getRepository)
val receiveCommand = new ReceiveCommand(headTip, commitId, headName)
// update pull request
updatePullRequests(repository.owner, repository.name, branch)
// call post commit hook
val error = PluginRegistry().getReceiveHooks.flatMap { hook =>
hook.preReceive(repository.owner, repository.name, receivePack, receiveCommand, loginAccount.userName)
}.headOption
// record activity
val commitInfo = new CommitInfo(JGitUtil.getRevCommitFromId(git, commitId))
recordPushActivity(repository.owner, repository.name, loginAccount.userName, branch, List(commitInfo))
error match {
case Some(error) =>
// commit is rejected
// TODO Notify commit failure to edited user
val refUpdate = git.getRepository.updateRef(headName)
refUpdate.setNewObjectId(headTip)
refUpdate.setForceUpdate(true)
refUpdate.update()
// create issue comment by commit message
createIssueComment(repository.owner, repository.name, commitInfo)
case None =>
// update refs
val refUpdate = git.getRepository.updateRef(headName)
refUpdate.setNewObjectId(commitId)
refUpdate.setForceUpdate(false)
refUpdate.setRefLogIdent(new PersonIdent(loginAccount.fullName, loginAccount.mailAddress))
refUpdate.update()
// close issue by commit message
closeIssuesFromMessage(message, loginAccount.userName, repository.owner, repository.name)
// update pull request
updatePullRequests(repository.owner, repository.name, branch)
//call web hook
callPullRequestWebHookByRequestBranch("synchronize", repository, branch, context.baseUrl, loginAccount)
val commit = new JGitUtil.CommitInfo(JGitUtil.getRevCommitFromId(git, commitId))
callWebHookOf(repository.owner, repository.name, WebHook.Push) {
getAccountByUserName(repository.owner).map{ ownerAccount =>
WebHookPushPayload(git, loginAccount, headName, repository, List(commit), ownerAccount,
oldId = headTip, newId = commitId)
}
// record activity
val commitInfo = new CommitInfo(JGitUtil.getRevCommitFromId(git, commitId))
recordPushActivity(repository.owner, repository.name, loginAccount.userName, branch, List(commitInfo))
// create issue comment by commit message
createIssueComment(repository.owner, repository.name, commitInfo)
// close issue by commit message
closeIssuesFromMessage(message, loginAccount.userName, repository.owner, repository.name)
// call post commit hook
PluginRegistry().getReceiveHooks.foreach { hook =>
hook.postReceive(repository.owner, repository.name, receivePack, receiveCommand, loginAccount.userName)
}
//call web hook
callPullRequestWebHookByRequestBranch("synchronize", repository, branch, context.baseUrl, loginAccount)
val commit = new JGitUtil.CommitInfo(JGitUtil.getRevCommitFromId(git, commitId))
callWebHookOf(repository.owner, repository.name, WebHook.Push) {
getAccountByUserName(repository.owner).map{ ownerAccount =>
WebHookPushPayload(git, loginAccount, headName, repository, List(commit), ownerAccount,
oldId = headTip, newId = commitId)
}
}
}
}
}

View File

@@ -12,7 +12,7 @@ import gitbucket.core.util.Implicits._
import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.Directory._
import gitbucket.core.util.StringUtil._
import io.github.gitbucket.scalatra.forms._
import org.scalatra.forms._
import org.apache.commons.io.{FileUtils, IOUtils}
import org.scalatra.i18n.Messages
import com.github.zafarkhaja.semver.{Version => Semver}

View File

@@ -0,0 +1,91 @@
package gitbucket.core.controller
import org.json4s.{JField, JObject, JString}
import org.scalatra._
import org.scalatra.json._
import org.scalatra.forms._
import org.scalatra.i18n.I18nSupport
import org.scalatra.servlet.ServletBase
/**
* Extends scalatra-forms to support the client-side validation and Ajax requests as well.
*/
trait ValidationSupport extends FormSupport { self: ServletBase with JacksonJsonSupport with I18nSupport =>
def get[T](path: String, form: ValueType[T])(action: T => Any): Route = {
registerValidate(path, form)
get(path){
validate(form)(errors => BadRequest(), form => action(form))
}
}
def post[T](path: String, form: ValueType[T])(action: T => Any): Route = {
registerValidate(path, form)
post(path){
validate(form)(errors => BadRequest(), form => action(form))
}
}
def put[T](path: String, form: ValueType[T])(action: T => Any): Route = {
registerValidate(path, form)
put(path){
validate(form)(errors => BadRequest(), form => action(form))
}
}
def delete[T](path: String, form: ValueType[T])(action: T => Any): Route = {
registerValidate(path, form)
delete(path){
validate(form)(errors => BadRequest(), form => action(form))
}
}
def ajaxGet[T](path: String, form: ValueType[T])(action: T => Any): Route = {
get(path){
validate(form)(errors => ajaxError(errors), form => action(form))
}
}
def ajaxPost[T](path: String, form: ValueType[T])(action: T => Any): Route = {
post(path){
validate(form)(errors => ajaxError(errors), form => action(form))
}
}
def ajaxDelete[T](path: String, form: ValueType[T])(action: T => Any): Route = {
delete(path){
validate(form)(errors => ajaxError(errors), form => action(form))
}
}
def ajaxPut[T](path: String, form: ValueType[T])(action: T => Any): Route = {
put(path){
validate(form)(errors => ajaxError(errors), form => action(form))
}
}
private def registerValidate[T](path: String, form: ValueType[T]) = {
post(path.replaceFirst("/$", "") + "/validate"){
contentType = "application/json"
toJson(form.validate("", multiParams, messages))
}
}
/**
* Responds errors for ajax requests.
*/
private def ajaxError(errors: Seq[(String, String)]): JObject = {
status = 400
contentType = "application/json"
toJson(errors)
}
/**
* Converts errors to JSON.
*/
private def toJson(errors: Seq[(String, String)]): JObject =
JObject(errors.map { case (key, value) =>
JField(key, JString(value))
}.toList)
}

View File

@@ -10,7 +10,7 @@ import gitbucket.core.util.StringUtil._
import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.Implicits._
import gitbucket.core.util.Directory._
import io.github.gitbucket.scalatra.forms._
import org.scalatra.forms._
import org.eclipse.jgit.api.Git
import org.scalatra.i18n.Messages
@@ -226,8 +226,8 @@ trait WikiControllerBase extends ControllerBase {
})
private def unique: Constraint = new Constraint(){
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Option[String] =
getWikiPageList(params("owner"), params("repository")).find(_ == value).map(_ => "Page already exists.")
override def validate(name: String, value: String, params: Map[String, Seq[String]], messages: Messages): Option[String] =
getWikiPageList(params.value("owner"), params.value("repository")).find(_ == value).map(_ => "Page already exists.")
}
private def pagename: Constraint = new Constraint(){

View File

@@ -8,6 +8,7 @@ import gitbucket.core.service.RepositoryService.RepositoryInfo
import gitbucket.core.service.SystemSettingsService.SystemSettings
import gitbucket.core.util.SyntaxSugars._
import io.github.gitbucket.solidbase.model.Version
import org.apache.sshd.server.Command
import play.twirl.api.Html
/**
@@ -241,6 +242,17 @@ abstract class Plugin {
*/
def suggestionProviders(registry: PluginRegistry, context: ServletContext, settings: SystemSettings): Seq[SuggestionProvider] = Nil
/**
* Override to add ssh command providers.
*/
val sshCommandProviders: Seq[PartialFunction[String, Command]] = Nil
/**
* Override to add ssh command providers.
*/
def sshCommandProviders(registry: PluginRegistry, context: ServletContext, settings: SystemSettings): Seq[PartialFunction[String, Command]] = Nil
/**
* This method is invoked in initialization of plugin system.
* Register plugin functionality to PluginRegistry.
@@ -312,6 +324,9 @@ abstract class Plugin {
(suggestionProviders ++ suggestionProviders(registry, context, settings)).foreach { suggestionProvider =>
registry.addSuggestionProvider(suggestionProvider)
}
(sshCommandProviders ++ sshCommandProviders(registry, context, settings)).foreach { sshCommandProvider =>
registry.addSshCommandProvider(sshCommandProvider)
}
}
/**

View File

@@ -22,6 +22,7 @@ import io.github.gitbucket.solidbase.Solidbase
import io.github.gitbucket.solidbase.manager.JDBCVersionManager
import io.github.gitbucket.solidbase.model.Module
import org.apache.commons.io.FileUtils
import org.apache.sshd.server.Command
import org.slf4j.LoggerFactory
import play.twirl.api.Html
@@ -40,12 +41,9 @@ class PluginRegistry {
private val accountHooks = new ConcurrentLinkedQueue[AccountHook]
private val receiveHooks = new ConcurrentLinkedQueue[ReceiveHook]
receiveHooks.add(new ProtectedBranchReceiveHook())
private val repositoryHooks = new ConcurrentLinkedQueue[RepositoryHook]
private val issueHooks = new ConcurrentLinkedQueue[IssueHook]
private val pullRequestHooks = new ConcurrentLinkedQueue[PullRequestHook]
private val repositoryHeaders = new ConcurrentLinkedQueue[(RepositoryInfo, Context) => Option[Html]]
private val globalMenus = new ConcurrentLinkedQueue[(Context) => Option[Link]]
private val repositoryMenus = new ConcurrentLinkedQueue[(RepositoryInfo, Context) => Option[Link]]
@@ -57,9 +55,9 @@ class PluginRegistry {
private val issueSidebars = new ConcurrentLinkedQueue[(Issue, RepositoryInfo, Context) => Option[Html]]
private val assetsMappings = new ConcurrentLinkedQueue[(String, String, ClassLoader)]
private val textDecorators = new ConcurrentLinkedQueue[TextDecorator]
private val suggestionProviders = new ConcurrentLinkedQueue[SuggestionProvider]
suggestionProviders.add(new UserNameSuggestionProvider())
private val sshCommandProviders = new ConcurrentLinkedQueue[PartialFunction[String, Command]]()
def addPlugin(pluginInfo: PluginInfo): Unit = plugins.add(pluginInfo)
@@ -178,6 +176,10 @@ class PluginRegistry {
def addSuggestionProvider(suggestionProvider: SuggestionProvider): Unit = suggestionProviders.add(suggestionProvider)
def getSuggestionProviders: Seq[SuggestionProvider] = suggestionProviders.asScala.toSeq
def addSshCommandProvider(sshCommandProvider: PartialFunction[String, Command]): Unit = sshCommandProviders.add(sshCommandProvider)
def getSshCommandProviders: Seq[PartialFunction[String, Command]] = sshCommandProviders.asScala.toSeq
}
/**

View File

@@ -3,6 +3,7 @@ package gitbucket.core.plugin
import gitbucket.core.controller.Context
import gitbucket.core.service.RepositoryService
import gitbucket.core.view.Markdown
import gitbucket.core.view.helpers.urlLink
import play.twirl.api.Html
/**
@@ -33,12 +34,7 @@ object MarkdownRenderer extends Renderer {
object DefaultRenderer extends Renderer {
override def render(request: RenderRequest): Html = {
import request._
Html(
s"<tt>${
fileContent.split("(\\r\\n)|\\n").map(xml.Utility.escape(_)).mkString("<br/>")
}</tt>"
)
Html(s"""<tt><pre class="plain">${urlLink(request.fileContent)}</pre></tt>""")
}
}
@@ -51,4 +47,4 @@ case class RenderRequest(
enableRefsLink: Boolean,
enableAnchor: Boolean,
context: Context
)
)

View File

@@ -3,15 +3,92 @@ package gitbucket.core.plugin
import gitbucket.core.controller.Context
import gitbucket.core.service.RepositoryService.RepositoryInfo
/**
* The base trait of suggestion providers which supplies completion proposals in some text areas.
*/
trait SuggestionProvider {
/**
* The identifier of this suggestion provider.
* You must specify the unique identifier in the all suggestion providers.
*/
val id: String
/**
* The trigger of this suggestion provider. When user types this character, the proposal list would be displayed.
* Also this is used as the prefix of the replaced string.
*/
val prefix: String
/**
* The suffix of the replaced string. The default is `" "`.
*/
val suffix: String = " "
/**
* Which contexts is this suggestion provider enabled. Currently, available contexts are `"issues"` and `"wiki"`.
*/
val context: Seq[String]
def values(repository: RepositoryInfo): Seq[String]
def template(implicit context: Context): String = "value"
/**
* If this suggestion provider has static proposal list, override this method to return it.
*
* The returned sequence is rendered as follows:
* <pre>
* [
* {
* "label" -> "value1",
* "value" -> "value1"
* },
* {
* "label" -> "value2",
* "value" -> "value2"
* },
* ]
* </pre>
*
* Each element can be accessed as `option` in `template()` or `replace()` method.
*/
def values(repository: RepositoryInfo): Seq[String] = Nil
/**
* If this suggestion provider has static proposal list, override this method to return it.
*
* If your proposals have label and value, use this method instead of `values()`.
* The first element of tuple is used as a value, and the second element is used as a label.
*
* The returned sequence is rendered as follows:
* <pre>
* [
* {
* "label" -> "label1",
* "value" -> "value1"
* },
* {
* "label" -> "label2",
* "value" -> "value2"
* },
* ]
* </pre>
*
* Each element can be accessed as `option` in `template()` or `replace()` method.
*/
def options(repository: RepositoryInfo): Seq[(String, String)] = values(repository).map { value => (value, value) }
/**
* JavaScript fragment to generate a label of completion proposal. The default is: `option.label`.
*/
def template(implicit context: Context): String = "option.label"
/**
* JavaScript fragment to generate a replaced value of completion proposal. The default is: `option.value`
*/
def replace(implicit context: Context): String = "option.value"
/**
* If this suggestion provider needs some additional process to assemble the proposal list (e.g. It need to use Ajax
* to get a proposal list from the server), then override this method and return any JavaScript code.
*/
def additionalScript(implicit context: Context): String = ""
}
@@ -20,8 +97,6 @@ class UserNameSuggestionProvider extends SuggestionProvider {
override val id: String = "user"
override val prefix: String = "@"
override val context: Seq[String] = Seq("issues")
override def values(repository: RepositoryInfo): Seq[String] = Nil
override def template(implicit context: Context): String = "'@' + value"
override def additionalScript(implicit context: Context): String =
s"""$$.get('${context.path}/_user/proposals', { query: '', user: true, group: false }, function (data) { user = data.options; });"""
}
}

View File

@@ -369,7 +369,14 @@ trait IssuesService {
def deleteComment(issueId: Int, commentId: Int)(implicit s: Session): Int = {
Issues.filter(_.issueId === issueId.bind).map(_.updatedDate).update(currentDate)
IssueComments.filter(_.byPrimaryKey(commentId)).delete
IssueComments.filter(_.byPrimaryKey(commentId)).firstOption match {
case Some(c) if c.action == "reopen_comment" =>
IssueComments.filter(_.byPrimaryKey(commentId)).map(t => (t.content, t.action)).update("Reopen", "reopen")
case Some(c) if c.action == "close_comment" =>
IssueComments.filter(_.byPrimaryKey(commentId)).map(t => (t.content, t.action)).update("Close", "close")
case Some(_) =>
IssueComments.filter(_.byPrimaryKey(commentId)).delete
}
}
def updateClosed(owner: String, repository: String, issueId: Int, closed: Boolean)(implicit s: Session): Int = {

View File

@@ -1,11 +1,10 @@
package gitbucket.core.service
import gitbucket.core.model.{ProtectedBranch, ProtectedBranchContext, CommitState}
import gitbucket.core.model.{Session => _, _}
import gitbucket.core.plugin.ReceiveHook
import gitbucket.core.model.Profile._
import gitbucket.core.model.Profile.profile.blockingApi._
import org.eclipse.jgit.transport.{ReceivePack, ReceiveCommand}
import org.eclipse.jgit.transport.{ReceiveCommand, ReceivePack}
trait ProtectedBranchService {
@@ -79,10 +78,19 @@ object ProtectedBranchService {
* Include administrators
* Enforce required status checks for repository administrators.
*/
includeAdministrators: Boolean) extends AccountService with CommitStatusService {
includeAdministrators: Boolean) extends AccountService with RepositoryService with CommitStatusService {
def isAdministrator(pusher: String)(implicit session: Session): Boolean =
pusher == owner || getGroupMembers(owner).exists(gm => gm.userName == pusher && gm.isManager)
pusher == owner || getGroupMembers(owner).exists(gm => gm.userName == pusher && gm.isManager) ||
getCollaborators(owner, repository).exists { case (collaborator, isGroup) =>
if(collaborator.role == Role.ADMIN.name){
if(isGroup){
getGroupMembers(collaborator.collaboratorName).exists(gm => gm.userName == pusher)
} else {
collaborator.collaboratorName == pusher
}
} else false
}
/**
* Can't be force pushed

View File

@@ -0,0 +1,69 @@
package gitbucket.core.servlet
import javax.servlet._
import javax.servlet.http.HttpServletRequest
import org.scalatra.ScalatraFilter
import scala.collection.mutable.ListBuffer
class CompositeScalatraFilter extends Filter {
private val filters = new ListBuffer[(ScalatraFilter, String)]()
def mount(filter: ScalatraFilter, path: String): Unit = {
filters += ((filter, path))
}
override def init(filterConfig: FilterConfig): Unit = {
filters.foreach { case (filter, _) =>
filter.init(filterConfig)
}
}
override def destroy(): Unit = {
filters.foreach { case (filter, _) =>
filter.destroy()
}
}
override def doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain): Unit = {
val contextPath = request.getServletContext.getContextPath
val requestPath = request.asInstanceOf[HttpServletRequest].getRequestURI.substring(contextPath.length)
val checkPath = if(requestPath.endsWith("/")){
requestPath
} else {
requestPath + "/"
}
filters
.filter { case (_, path) =>
val start = path.replaceFirst("/\\*$", "/")
checkPath.startsWith(start)
}
.foreach { case (filter, _) =>
val mockChain = new MockFilterChain()
filter.doFilter(request, response, mockChain)
if(mockChain.continue == false){
return ()
}
}
chain.doFilter(request, response)
}
}
class MockFilterChain extends FilterChain {
var continue: Boolean = false
override def doFilter(request: ServletRequest, response: ServletResponse): Unit = {
continue = true
}
}
class FilterChainFilter(chain: FilterChain) extends Filter {
override def init(filterConfig: FilterConfig): Unit = ()
override def destroy(): Unit = ()
override def doFilter(request: ServletRequest, response: ServletResponse, mockChain: FilterChain) = chain.doFilter(request, response)
}

View File

@@ -351,7 +351,6 @@ class WikiCommitHook(owner: String, repository: String, pusher: String, baseUrl:
diffs._1.collect { case diff if diff.newPath.toLowerCase.endsWith(".md") =>
val action = if(diff.changeType == ChangeType.ADD) "created" else "edited"
val fileName = diff.newPath
//println(action + " - " + fileName + " - " + commit.id)
(action, fileName, commit.id)
}
}

View File

@@ -21,25 +21,27 @@ class PluginControllerFilter extends Filter {
}
override def doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain): Unit = {
val controller = PluginRegistry().getControllers().filter { case (_, path) =>
val requestUri = request.asInstanceOf[HttpServletRequest].getRequestURI
val start = path.replaceFirst("/\\*$", "/")
(requestUri + "/").startsWith(start)
}
val requestUri = request.asInstanceOf[HttpServletRequest].getRequestURI
val filterChainWrapper = controller.foldLeft(chain){ case (chain, (controller, _)) =>
new FilterChainWrapper(controller, chain)
}
filterChainWrapper.doFilter(request, response)
}
class FilterChainWrapper(controller: ControllerBase, chain: FilterChain) extends FilterChain {
override def doFilter(request: ServletRequest, response: ServletResponse): Unit = {
if(controller.config == null){
controller.init(filterConfig)
PluginRegistry().getControllers()
.filter { case (_, path) =>
val start = path.replaceFirst("/\\*$", "/")
(requestUri + "/").startsWith(start)
}
controller.doFilter(request, response, chain)
}
.foreach { case (controller, _) =>
controller match {
case x: ControllerBase if(x.config == null) => x.init(filterConfig)
case _ => ()
}
val mockChain = new MockFilterChain()
controller.doFilter(request, response, mockChain)
if(mockChain.continue == false){
return ()
}
}
chain.doFilter(request, response)
}
}

View File

@@ -23,7 +23,7 @@ class TransactionFilter extends Filter {
def doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain): Unit = {
val servletPath = req.asInstanceOf[HttpServletRequest].getServletPath()
if(servletPath.startsWith("/assets/") || servletPath == "/git" || servletPath == "/git-lfs"){
if(servletPath.startsWith("/assets/") || servletPath == "/console" || servletPath == "/git" || servletPath == "/git-lfs"){
// assets and git-lfs don't need transaction
chain.doFilter(req, res)
} else {

View File

@@ -223,12 +223,19 @@ class GitCommandFactory(baseUrl: String, sshUrl: Option[String]) extends Command
import GitCommand._
logger.debug(s"command: $command")
command match {
case SimpleCommandRegex ("upload" , repoName) if(pluginRepository(repoName)) => new PluginGitUploadPack (repoName, routing(repoName))
case SimpleCommandRegex ("receive", repoName) if(pluginRepository(repoName)) => new PluginGitReceivePack(repoName, routing(repoName))
case DefaultCommandRegex("upload" , owner, repoName) => new DefaultGitUploadPack (owner, repoName)
case DefaultCommandRegex("receive", owner, repoName) => new DefaultGitReceivePack(owner, repoName, baseUrl, sshUrl)
case _ => new UnknownCommand(command)
val pluginCommand = PluginRegistry().getSshCommandProviders.collectFirst {
case f if f.isDefinedAt(command) => f(command)
}
pluginCommand match {
case Some(x) => x
case None => command match {
case SimpleCommandRegex ("upload" , repoName) if(pluginRepository(repoName)) => new PluginGitUploadPack (repoName, routing(repoName))
case SimpleCommandRegex ("receive", repoName) if(pluginRepository(repoName)) => new PluginGitReceivePack(repoName, routing(repoName))
case DefaultCommandRegex("upload" , owner, repoName) => new DefaultGitUploadPack (owner, repoName)
case DefaultCommandRegex("receive", owner, repoName) => new DefaultGitReceivePack(owner, repoName, baseUrl, sshUrl)
case _ => new UnknownCommand(command)
}
}
}

View File

@@ -53,4 +53,14 @@ object SyntaxSugars {
def unapply[A, B](t: (A, B)): Option[(A, B)] = Some(t)
}
/**
* Provides easier and explicit ways to access to a head value of `Map[String, Seq[String]]`.
* This is intended to use in implementations of scalatra-forms's `Constraint` or `ValueType`.
*/
implicit class HeadValueAccessibleMap(map: Map[String, Seq[String]]){
def value(key: String): String = map(key).head
def optionValue(key: String): Option[String] = map.get(key).flatMap(_.headOption)
def values(key: String): Seq[String] = map.get(key).getOrElse(Seq.empty)
}
}

View File

@@ -1,6 +1,6 @@
package gitbucket.core.util
import io.github.gitbucket.scalatra.forms._
import org.scalatra.forms._
import org.scalatra.i18n.Messages
trait Validations {

View File

@@ -346,10 +346,10 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache
}
// This pattern comes from: http://stackoverflow.com/a/4390768/1771641 (extract-url-from-string)
private[this] val detectAndRenderLinksRegex = """(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,13}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))""".r
private[this] val urlRegex = """(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,13}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))""".r
def detectAndRenderLinks(text: String, repository: RepositoryInfo)(implicit context: Context): String = {
val matches = detectAndRenderLinksRegex.findAllMatchIn(text).toSeq
def urlLink(text: String): String = {
val matches = urlRegex.findAllMatchIn(text).toSeq
val (x, pos) = matches.foldLeft((collection.immutable.Seq.empty[Html], 0)){ case ((x, pos), m) =>
val url = m.group(0)
@@ -361,8 +361,7 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache
}
// append rest fragment
val out = if (pos < text.length) x :+ HtmlFormat.escape(text.substring(pos)) else x
decorateHtml(HtmlFormat.fill(out).toString, repository)
HtmlFormat.fill(out).toString
}
/**

View File

@@ -56,7 +56,6 @@
<a href="@context.path/@account.userName/_delete" class="btn btn-danger" id="delete">Delete account</a>
</div>
<input type="submit" class="btn btn-success" value="Save"/>
@if(!LDAPUtil.isDummyMailAddress(account)){<a href="@helpers.url(account.userName)" class="btn btn-default">Cancel</a>}
</div>
</form>
}

View File

@@ -35,7 +35,7 @@
@menu(context).map { link =>
<li@if(active==link.id){ class="active"}>
<a href="@context.path/@link.path">
<i class="menu-icon octicon octicon-plug"></i>
<i class="menu-icon octicon octicon-@link.icon.getOrElse("plug")"></i>
<span>@link.label</span>
</a>
</li>

View File

@@ -60,6 +60,44 @@
<textarea name="information" class="form-control" style="height: 100px;">@context.settings.information</textarea>
</fieldset>
<!--====================================================================-->
<!-- AdminLTE SkinName -->
<!--====================================================================-->
<hr>
<label class="strong">
AdminLTE skin name
</label>
<div class="form-group">
<label class="control-label col-md-2" for="skinName">Skin name</label>
<div class="col-md-10">
<select id="skinName" name="skinName" class="form-control">
<optgroup label="Dark">
@Seq(
("skin-black", "Black"),
("skin-blue", "Blue"),
("skin-green", "Green"),
("skin-purple", "Purple"),
("skin-red", "Red"),
("skin-yellow", "Yellow"),
).map{ skin =>
<option value="@skin._1"@if(skin._1 == context.settings.skinName){ selected=""}>@skin._2</option>
}
</optgroup>
<optgroup label="Light">
@Seq(
("skin-black-light", "Light black"),
("skin-blue-light", "Light blue"),
("skin-green-light", "Light green"),
("skin-purple-light", "Light purple"),
("skin-red-light", "Light red"),
("skin-yellow-light", "Light yellow"),
).map{ skin =>
<option value="@skin._1"@if(skin._1 == context.settings.skinName){ selected=""} >@skin._2</option>
}
</optgroup>
</select>
</div>
</div>
<!--====================================================================-->
<!-- Account registration -->
<!--====================================================================-->
<hr>
@@ -108,8 +146,8 @@
<label><span class="strong">Limit of activity logs</span> (Unlimited if it is not specified or zero)</label>
<fieldset>
<div class="form-group">
<label class="control-label col-md-3" for="activityLogLimit">Limit</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="activityLogLimit">Limit</label>
<div class="col-md-10">
<input type="text" id="activityLogLimit" name="activityLogLimit" class="form-control input-mini" value="@context.settings.activityLogLimit"/>
<span id="error-activityLogLimit" class="error"></span>
</div>
@@ -140,15 +178,15 @@
</fieldset>
<div class="ssh">
<div class="form-group">
<label class="control-label col-md-3" for="sshHost">SSH host</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="sshHost">SSH host</label>
<div class="col-md-10">
<input type="text" id="sshHost" name="sshHost" class="form-control" value="@context.settings.sshHost"/>
<span id="error-sshHost" class="error"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="sshPort">SSH port</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="sshPort">SSH port</label>
<div class="col-md-10">
<input type="text" id="sshPort" name="sshPort" class="form-control" value="@context.settings.sshPort"/>
<span id="error-sshPort" class="error"></span>
</div>
@@ -167,83 +205,83 @@
</fieldset>
<div class="ldap">
<div class="form-group">
<label class="control-label col-md-3" for="ldapHost">LDAP host</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="ldapHost">LDAP host</label>
<div class="col-md-10">
<input type="text" id="ldapHost" name="ldap.host" class="form-control" value="@context.settings.ldap.map(_.host)"/>
<span id="error-ldap_host" class="error"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="ldapPort">LDAP port</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="ldapPort">LDAP port</label>
<div class="col-md-10">
<input type="text" id="ldapPort" name="ldap.port" class="form-control input-mini" value="@context.settings.ldap.map(_.port)"/>
<span id="error-ldap_port" class="error"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="ldapBindDN">Bind DN</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="ldapBindDN">Bind DN</label>
<div class="col-md-10">
<input type="text" id="ldapBindDN" name="ldap.bindDN" class="form-control" value="@context.settings.ldap.map(_.bindDN)"/>
<span id="error-ldap_bindDN" class="error"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="ldapBindPassword">Bind password</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="ldapBindPassword">Bind password</label>
<div class="col-md-10">
<input type="password" id="ldapBindPassword" name="ldap.bindPassword" class="form-control" value="@context.settings.ldap.map(_.bindPassword)"/>
<span id="error-ldap_bindPassword" class="error"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="ldapBaseDN">Base DN</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="ldapBaseDN">Base DN</label>
<div class="col-md-10">
<input type="text" id="ldapBaseDN" name="ldap.baseDN" class="form-control" value="@context.settings.ldap.map(_.baseDN)"/>
<span id="error-ldap_baseDN" class="error"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="ldapUserNameAttribute">User name attribute</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="ldapUserNameAttribute">User name attribute</label>
<div class="col-md-10">
<input type="text" id="ldapUserNameAttribute" name="ldap.userNameAttribute" class="form-control" value="@context.settings.ldap.map(_.userNameAttribute)"/>
<span id="error-ldap_userNameAttribute" class="error"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="ldapAdditionalFilterCondition">Additional filter condition</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="ldapAdditionalFilterCondition">Additional filter condition</label>
<div class="col-md-10">
<input type="text" id="ldapAdditionalFilterCondition" name="ldap.additionalFilterCondition" class="form-control" value="@context.settings.ldap.map(_.additionalFilterCondition)"/>
<span id="error-ldap_additionalFilterCondition" class="error"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="ldapFullNameAttribute">Full name attribute</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="ldapFullNameAttribute">Full name attribute</label>
<div class="col-md-10">
<input type="text" id="ldapFullNameAttribute" name="ldap.fullNameAttribute" class="form-control" value="@context.settings.ldap.map(_.fullNameAttribute)"/>
<span id="error-ldap_fullNameAttribute" class="error"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="ldapMailAttribute">Mail address attribute</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="ldapMailAttribute">Mail address attribute</label>
<div class="col-md-10">
<input type="text" id="ldapMailAttribute" name="ldap.mailAttribute" class="form-control" value="@context.settings.ldap.map(_.mailAttribute)"/>
<span id="error-ldap_mailAttribute" class="error"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3">Enable TLS</label>
<div class="col-md-9">
<label class="control-label col-md-2">Enable TLS</label>
<div class="col-md-10">
<input type="checkbox" name="ldap.tls"@if(context.settings.ldap.flatMap(_.tls).getOrElse(false)){ checked}/>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3">Enable SSL</label>
<div class="col-md-9">
<label class="control-label col-md-2">Enable SSL</label>
<div class="col-md-10">
<input type="checkbox" name="ldap.ssl"@if(context.settings.ldap.flatMap(_.ssl).getOrElse(false)){ checked}/>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="ldapBindDN">Keystore</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="ldapBindDN">Keystore</label>
<div class="col-md-10">
<input type="text" id="ldapKeystore" name="ldap.keystore" class="form-control" value="@context.settings.ldap.map(_.keystore)"/>
<span id="error-ldap_keystore" class="error"></span>
</div>
@@ -274,52 +312,52 @@
</fieldset>
<div class="useSMTP">
<div class="form-group">
<label class="control-label col-md-3" for="smtpHost">SMTP host</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="smtpHost">SMTP host</label>
<div class="col-md-10">
<input type="text" id="smtpHost" name="smtp.host" class="form-control" value="@context.settings.smtp.map(_.host)"/>
<span id="error-smtp_host" class="error"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="smtpPort">SMTP port</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="smtpPort">SMTP port</label>
<div class="col-md-10">
<input type="text" id="smtpPort" name="smtp.port" class="form-control input-mini" value="@context.settings.smtp.map(_.port)"/>
<span id="error-smtp_port" class="error"></span>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="smtpUser">SMTP user</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="smtpUser">SMTP user</label>
<div class="col-md-10">
<input type="text" id="smtpUser" name="smtp.user" class="form-control" value="@context.settings.smtp.map(_.user)"/>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="smtpPassword">SMTP password</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="smtpPassword">SMTP password</label>
<div class="col-md-10">
<input type="password" id="smtpPassword" name="smtp.password" class="form-control" value="@context.settings.smtp.map(_.password)"/>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="smtpSsl">Enable SSL</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="smtpSsl">Enable SSL</label>
<div class="col-md-10">
<input type="checkbox" id="smtpSsl" name="smtp.ssl"@if(context.settings.smtp.flatMap(_.ssl).getOrElse(false)){ checked}/>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="smtpStarttls">Enable STARTTLS</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="smtpStarttls">Enable STARTTLS</label>
<div class="col-md-10">
<input type="checkbox" id="smtpStarttls" name="smtp.starttls"@if(context.settings.smtp.flatMap(_.starttls).getOrElse(false)){ checked}/>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="fromAddress">FROM address</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="fromAddress">FROM address</label>
<div class="col-md-10">
<input type="text" id="fromAddress" name="smtp.fromAddress" class="form-control" value="@context.settings.smtp.map(_.fromAddress)"/>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3" for="fromName">FROM name</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="fromName">FROM name</label>
<div class="col-md-10">
<input type="text" id="fromName" name="smtp.fromName" class="form-control" value="@context.settings.smtp.map(_.fromName)"/>
</div>
</div>
@@ -329,52 +367,22 @@
<input type="button" id="sendTestMail" value="Send"/>
</div>
</div>
@*
<!--====================================================================-->
<!-- GitLFS -->
<!--====================================================================-->
@*
<hr>
<label class="strong">
GitLFS <span class="muted normal">(Enter the LFS server url to enable GitLFS support)</span>
</label>
<div class="form-group">
<label class="control-label col-md-3" for="smtpHost">LFS server url</label>
<div class="col-md-9">
<label class="control-label col-md-2" for="smtpHost">LFS server url</label>
<div class="col-md-10">
<input type="text" id="lfsServerUrl" name="lfs.serverUrl" class="form-control" value="@context.settings.lfs.serverUrl"/>
<span id="error-lfs_serverUrl" class="error"></span>
</div>
</div>
*@
<!--====================================================================-->
<!-- AdminLTE SkinName -->
<!--====================================================================-->
<hr>
<label class="strong">
AdminLTE skin name
</label>
<div class="form-group">
<label class="control-label col-md-3" for="skinName">Skin name</label>
<div class="col-md-9">
<select id="skinName" name="skinName">
@Seq(
"skin-black",
"skin-black-light",
"skin-blue",
"skin-blue-light",
"skin-green",
"skin-green-light",
"skin-purple",
"skin-purple-light",
"skin-red",
"skin-red-light",
"skin-yellow",
"skin-yellow-light",
).map{ skin =>
<option @if(skin == context.settings.skinName){selected}>@skin</option>
}
</select>
</div>
</div>
</div>
</div>
<div class="align-right" style="margin-top: 20px;">
@@ -385,6 +393,14 @@
}
<script>
$(function(){
$('#skinName').change(function(evt) {
var that = $(evt.target);
var themeCss = $('link[rel="stylesheet"][href*="skin-"]');
var oldVal = new RegExp('(skin-.*?).min.css').exec(themeCss.attr('href'))[1];
themeCss.attr('href', themeCss.attr('href').replace(oldVal, that.val()));
$(document.body).removeClass(oldVal).addClass(that.val());
});
$('#sendTestMail').click(function(){
var host = $('#smtpHost' ).val();
var port = $('#smtpPort' ).val();

View File

@@ -5,7 +5,7 @@
<h1>@title</h1>
@if(context.loginAccount.map{_.isAdmin}.getOrElse(false)){
@e.map { ex =>
<h2>@ex.getMessage</h2>
<h2>@ex.toString</h2>
<table class="table table-condensed table-striped table-hover">
<tbody>
@ex.getStackTrace.map{ st =>

View File

@@ -17,6 +17,12 @@ $(function(){
function (data) {
return process(data.options);
});
},
displayText: function(item) {
return item.label;
},
afterSelect: function(item) {
$('#@id').val(item.value);
}
});
});

View File

@@ -11,7 +11,9 @@
$(function(){
@gitbucket.core.plugin.PluginRegistry().getSuggestionProviders.map { provider =>
@if(provider.context.contains(completionContext)){
var @provider.id = @Html(helpers.json(provider.values(repository)));
var @provider.id = @Html(helpers.json(provider.options(repository).map { case (value, label) =>
Map("value" -> value, "label" -> label)
}));
@Html(provider.additionalScript)
}
}
@@ -23,14 +25,14 @@ $(function(){
match: /\B@{provider.prefix}([\-+\w]*)$/,
search: function (term, callback) {
callback($.map(@{provider.id}, function (proposal) {
return proposal.indexOf(term) === 0 ? proposal : null;
return proposal.value.indexOf(term) === 0 ? proposal : null;
}));
},
template: function (value) {
template: function (option) {
return @{Html(provider.template)};
},
replace: function (value) {
return '@{provider.prefix}' + value + '@{provider.suffix}';
replace: function (option) {
return '@{provider.prefix}' + @{Html(provider.replace)} + '@{provider.suffix}';
},
index: 1
},

View File

@@ -4,7 +4,8 @@
@import gitbucket.core.view.helpers
@gitbucket.core.helper.html.dropdown(
value = if(branch.length == 40) branch.substring(0, 10) else branch,
prefix = if(branch.length == 40) "tree" else if(repository.branchList.contains(branch)) "branch" else "tree"
prefix = if(branch.length == 40) "tree" else if(repository.branchList.contains(branch)) "branch" else "tree",
maxValueWidth = "200px"
) {
<li><div id="branch-control-title">Switch branches<button id="branch-control-close" class="pull-right">&times</button></div></li>
<li><input id="branch-control-input" type="text" class="form-control input-sm dropdown-filter-input" placeholder="Find or create branch ..."/></li>

View File

@@ -10,7 +10,7 @@
@import org.eclipse.jgit.diff.DiffEntry.ChangeType
@if(showIndex){
<div class="pull-right" style="margin-bottom: 10px;">
<div class="btn-group" data-toggle="buttons-radio">
<div class="btn-group" data-toggle="buttons">
<input type="button" id="btn-unified" class="btn btn-default btn-small active" value="Unified">
<input type="button" id="btn-split" class="btn btn-default btn-small" value="Split">
</div>
@@ -151,20 +151,21 @@ $(function(){
}
window.viewType = 1;
if(("&" + location.search.substring(1)).indexOf("&diff=split") != -1){
$('.container').removeClass('container').addClass('container-wide');
window.viewType = 0;
}
renderDiffs();
$('#btn-unified').click(function(){
window.viewType = 1;
$('.container-wide').removeClass('container-wide').addClass('container');
$('#btn-unified').addClass('active');
$('#btn-split').removeClass('active');
renderDiffs();
});
$('#btn-split').click(function(){
window.viewType = 0;
$('.container').removeClass('container').addClass('container-wide');
$('#btn-unified').removeClass('active');
$('#btn-split').addClass('active');
renderDiffs();
});
@@ -174,6 +175,7 @@ $(function(){
}
$(this).closest('table').find('.not-diff').toggle();
});
$('.ignore-whitespace').change(function() {
renderOneDiff($(this).closest("table").find(".diffText"), viewType);
});
@@ -188,22 +190,56 @@ $(function(){
}
return $('<tr class="not-diff"><td colspan="3" class="comment-box-container"></td></tr>');
}
if (typeof $('#show-notes')[0] !== 'undefined' && !$('#show-notes')[0].checked) {
$('#comment-list').children('.inline-comment').hide();
}
function showCommentForm(commitId, fileName, oldLineNumber, newLineNumber, $tr){
// assemble Ajax url
var url = '@helpers.url(repository)/commit/' + commitId + '/comment/_form?fileName=' + fileName@issueId.map { id => + '&issueId=@id' };
if (!isNaN(oldLineNumber) && oldLineNumber) {
url += ('&oldLineNumber=' + oldLineNumber)
}
if (!isNaN(newLineNumber) && newLineNumber) {
url += ('&newLineNumber=' + newLineNumber)
}
// send Ajax request
$.get(url, { dataType : 'html' }, function(responseContent) {
// create container
var tmp;
if (!isNaN(oldLineNumber) && oldLineNumber) {
if (!isNaN(newLineNumber) && newLineNumber) {
tmp = getInlineContainer();
} else {
tmp = getInlineContainer('old');
}
} else {
tmp = getInlineContainer('new');
}
// add comment textarea
tmp.addClass('inline-comment-form').children('.comment-box-container').html(responseContent);
$tr.nextAll(':not(.not-diff):first').before(tmp);
// hide reply comment field
$(tmp).closest('.not-diff').prev().find('.reply-comment').closest('.not-diff').hide();
// focus textarea
tmp.find('textarea').focus();
});
}
// Add comment button
$('.diff-outside').on('click','table.diff .add-comment',function() {
var $this = $(this);
var $tr = $this.closest('tr');
var $check = $this.closest('table:not(.diff)').find('.toggle-notes');
var url = '';
//var url = '';
if (!$check.prop('checked')) {
$check.prop('checked', true).trigger('change');
}
if (!$tr.nextAll(':not(.not-diff):first').prev().hasClass('inline-comment-form')) {
var commitId = $this.closest('.table-bordered').attr('commitId'),
fileName = $this.closest('.table-bordered').attr('fileName'),
oldLineNumber, newLineNumber,
url = '@helpers.url(repository)/commit/' + commitId + '/comment/_form?fileName=' + fileName@issueId.map { id => + '&issueId=@id' };
oldLineNumber, newLineNumber;
if (viewType == 0) {
oldLineNumber = $this.parent().prev('.oldline').attr('line-number');
newLineNumber = $this.parent().prev('.newline').attr('line-number');
@@ -211,30 +247,27 @@ $(function(){
oldLineNumber = $this.parent().prevAll('.oldline').attr('line-number');
newLineNumber = $this.parent().prevAll('.newline').attr('line-number');
}
if (!isNaN(oldLineNumber) && oldLineNumber) {
url += ('&oldLineNumber=' + oldLineNumber)
}
if (!isNaN(newLineNumber) && newLineNumber) {
url += ('&newLineNumber=' + newLineNumber)
}
$.get(url, { dataType : 'html' }, function(responseContent) {
var tmp;
if (!isNaN(oldLineNumber) && oldLineNumber) {
if (!isNaN(newLineNumber) && newLineNumber) {
tmp = getInlineContainer();
} else {
tmp = getInlineContainer('old');
}
} else {
tmp = getInlineContainer('new');
}
tmp.addClass('inline-comment-form').children('.comment-box-container').html(responseContent);
$tr.nextAll(':not(.not-diff):first').before(tmp);
});
showCommentForm(commitId, fileName, oldLineNumber, newLineNumber, $tr);
}
}).on('click', 'table.diff .btn-default', function() {
// Cancel comment form
$(this).closest('.not-diff').prev().find('.reply-comment').closest('.not-diff').show();
$(this).closest('.inline-comment-form').remove();
});
// Reply comment
$('.diff-outside').on('click', '.reply-comment',function(){
var $this = $(this);
var $tr = $this.closest('tr');
var commitId = $this.closest('.table-bordered').attr('commitId');
var fileName = $this.data('filename');
var oldLineNumber = $this.data('oldline');
var newLineNumber = $this.data('newline');
showCommentForm(commitId, fileName, oldLineNumber, newLineNumber, $tr);
});
function renderOneCommitCommentIntoDiff($v, diff){
var filename = $v.attr('filename');
var oldline = $v.attr('oldline');
@@ -257,6 +290,7 @@ $(function(){
tmp.hide();
}
}
function renderStatBar(add, del){
if(add + del > 5){
if(add){
@@ -282,6 +316,7 @@ $(function(){
}
return ret;
}
function renderOneDiff(diffText, viewType){
var table = diffText.closest("table[data-diff-id]");
var i = table.data("diff-id");
@@ -305,12 +340,59 @@ $(function(){
}
});
}
return table;
}
function renderReplyComment($table){
var elements = {};
var filename, newline, oldline;
$table.find('.comment-box-container .inline-comment').each(function(i, e){
filename = $(e).attr('filename');
newline = $(e).attr('newline');
oldline = $(e).attr('oldline');
var key = filename + '-' + newline + '-' + oldline;
elements[key] = {
element: $(e),
filename: filename,
newline: newline,
oldline: oldline
};
});
for(var key in elements){
filename = elements[key]['filename'];
oldline = elements[key]['oldline'];
newline = elements[key]['newline'];
var $v = $('<div class="commit-comment-box reply-comment-box">')
.append($('<input type="text" class="form-control reply-comment" placeholder="Reply...">')
.data('filename', filename)
.data('newline', newline)
.data('oldline', oldline));
var tmp;
if (typeof oldline !== 'undefined') {
if (typeof newline !== 'undefined') {
tmp = getInlineContainer();
} else {
tmp = getInlineContainer('old');
}
tmp.children('td:first').html($v);
} else {
tmp = getInlineContainer('new');
tmp.children('td:last').html($v);
}
elements[key]['element'].closest('.not-diff').after(tmp);
}
}
function renderDiffs(){
var i = 0, diffs = $('.diffText');
function render(){
if(diffs[i]){
renderOneDiff($(diffs[i]), viewType);
var $table = renderOneDiff($(diffs[i]), viewType);
@if(hasWritePermission) {
renderReplyComment($table);
}
i++;
setTimeout(render);
}

View File

@@ -1,11 +1,12 @@
@(value : String = "",
prefix: String = "",
style : String = "",
maxValueWidth : String = "",
right : Boolean = false,
filter: (String, String) = ("",""))(body: Html)
@defining(if(filter._1.isEmpty) "" else filter._1 + "-" + scala.util.Random.alphanumeric.take(4).mkString){ filterId =>
<div class="btn-group" @if(style.nonEmpty){style="@style"}>
<button
<button id = "test"
class="dropdown-toggle btn btn-default btn-sm" data-toggle="dropdown">
@if(value.isEmpty){
<i class="octicon octicon-gear"></i>
@@ -13,7 +14,10 @@
@if(prefix.nonEmpty){
<span class="muted">@prefix:</span>
}
<span class="strong">@value</span>
<span class="strong"
@if(maxValueWidth.nonEmpty){style="display:inline-block; vertical-align:bottom; overflow-x:hidden; max-width:@maxValueWidth; text-overflow:ellipsis"}>
@value
</span>
}
<span class="caret"></span>
</button>
@@ -26,7 +30,7 @@
</div>
@if(filterId.nonEmpty) {
<script>
$(window).load(function(){
$(window).on('load', function(){
$('#@{filterId}-input').parent().click(function(e) {
e.stopPropagation();
});

View File

@@ -201,7 +201,6 @@ $(function(){
$.post('@helpers.url(repository)/issue_comments/delete/' + id,
function(data){
if(data > 0) {
$('#comment-' + id).prev('div.issue-avatar-image').remove();
$('#comment-' + id).remove();
}
});
@@ -230,7 +229,6 @@ $(function(){
function(data){
if(data > 0) {
$('.commit-comment-' + id).closest('.not-diff').remove();
$('.commit-comment-' + id).closest('.inline-comment').remove();
}
});
}

View File

@@ -40,7 +40,7 @@
<script>
$(function(){
$('#new-label-button').click(function(e){
if($('#edit-label-area-new').size() != 0){
if($('#edit-label-area-new').length != 0){
$('div#edit-label-area-new').remove();
$('#new-label-table').hide();
} else {

View File

@@ -38,7 +38,7 @@
<script>
$(function(){
$('#new-priority-button').click(function(e){
if($('#edit-priority-area-new').size() != 0){
if($('#edit-priority-area-new').length != 0){
$('div#edit-priority-area-new').remove();
$('#new-priority-table').hide();
} else {

View File

@@ -9,51 +9,53 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="icon" href="@helpers.assets("/common/images/gitbucket.png")" type="image/vnd.microsoft.icon" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="@helpers.assets("/vendors/bootstrap-3.3.6/css/bootstrap.min.css")" rel="stylesheet">
<link href="@helpers.assets("/vendors/octicons-4.2.0/octicons.css")" rel="stylesheet">
<link href="@helpers.assets("/vendors/google-fonts/css/source-sans-pro.css")" rel="stylesheet">
<link href="@helpers.assets("/vendors/bootstrap-3.3.7/css/bootstrap.min.css")" rel="stylesheet">
<link href="@helpers.assets("/vendors/octicons-4.4.0/octicons.min.css")" rel="stylesheet">
<link href="@helpers.assets("/vendors/bootstrap-datetimepicker-4.17.44/css/bootstrap-datetimepicker.min.css")" rel="stylesheet">
<link href="@helpers.assets("/vendors/colorpicker/css/bootstrap-colorpicker.css")" rel="stylesheet">
<link href="@helpers.assets("/vendors/colorpicker/css/bootstrap-colorpicker.min.css")" rel="stylesheet">
<link href="@helpers.assets("/vendors/google-code-prettify/prettify.css")" type="text/css" rel="stylesheet"/>
<link href="@helpers.assets("/vendors/facebox/facebox.css")" rel="stylesheet"/>
<link href="@helpers.assets("/vendors/AdminLTE-2.3.11/css/AdminLTE.min.css")" rel="stylesheet">
<link href="@helpers.assets(s"/vendors/AdminLTE-2.3.11/css/skins/${context.settings.skinName}.min.css")" rel="stylesheet">
<link href="@helpers.assets("/vendors/font-awesome-4.6.3/css/font-awesome.min.css")" rel="stylesheet">
<link href="@helpers.assets("/vendors/AdminLTE-2.4.2/css/AdminLTE.min.css")" rel="stylesheet">
<link href="@helpers.assets(s"/vendors/AdminLTE-2.4.2/css/skins/${context.settings.skinName}.min.css")" rel="stylesheet">
<link href="@helpers.assets("/vendors/font-awesome-4.7.0/css/font-awesome.min.css")" rel="stylesheet">
<link href="@helpers.assets("/vendors/jquery-ui/jquery-ui.min.css")" rel="stylesheet">
<link href="@helpers.assets("/vendors/jquery-ui/jquery-ui.structure.min.css")" rel="stylesheet">
<link href="@helpers.assets("/vendors/jquery-ui/jquery-ui.theme.min.css")" rel="stylesheet">
<link href="@helpers.assets("/common/css/gitbucket.css")" rel="stylesheet">
<script src="@helpers.assets("/vendors/jquery/jquery-1.12.2.min.js")"></script>
<script src="@helpers.assets("/vendors/jquery/jquery-3.2.1.min.js")"></script>
<script src="@helpers.assets("/vendors/jquery-ui/jquery-ui.min.js")"></script>
<script src="@helpers.assets("/vendors/dropzone/dropzone.js")"></script>
<script src="@helpers.assets("/vendors/dropzone/dropzone.min.js")"></script>
<script src="@helpers.assets("/common/js/validation.js")"></script>
<script src="@helpers.assets("/common/js/gitbucket.js")"></script>
<script src="@helpers.assets("/vendors/bootstrap-3.3.6/js/bootstrap.js")"></script>
<script src="@helpers.assets("/vendors/bootstrap3-typeahead/bootstrap3-typeahead.js")"></script>
<script src="@helpers.assets("/vendors/bootstrap-3.3.7/js/bootstrap.min.js")"></script>
<script src="@helpers.assets("/vendors/bootstrap3-typeahead/bootstrap3-typeahead.min.js")"></script>
<script src="@helpers.assets("/vendors/bootstrap-datetimepicker-4.17.44/js/moment.min.js")"></script>
<script src="@helpers.assets("/vendors/bootstrap-datetimepicker-4.17.44/js/bootstrap-datetimepicker.min.js")"></script>
<script src="@helpers.assets("/vendors/colorpicker/js/bootstrap-colorpicker.js")"></script>
<script src="@helpers.assets("/vendors/colorpicker/js/bootstrap-colorpicker.min.js")"></script>
<script src="@helpers.assets("/vendors/google-code-prettify/prettify.js")"></script>
<script src="@helpers.assets("/vendors/elastic/jquery.elastic.source.js")"></script>
<script src="@helpers.assets("/vendors/facebox/facebox.js")"></script>
<script src="@helpers.assets("/vendors/jquery-hotkeys/jquery.hotkeys.js")"></script>
<script src="@helpers.assets("/vendors/jquery-textcomplete-1.6.2/jquery.textcomplete.js")"></script>
<script src="@helpers.assets("/vendors/jquery-textcomplete-1.8.4/jquery.textcomplete.min.js")"></script>
@repository.map { repository =>
<meta name="go-import" content="@context.baseUrl.replaceFirst("^https?://", "")/@repository.owner/@repository.name git @repository.httpUrl" />
}
<script src="@helpers.assets("/vendors/AdminLTE-2.3.11/js/app.js")" type="text/javascript"></script>
<script src="@helpers.assets("/vendors/AdminLTE-2.4.2/js/adminlte.min.js")" type="text/javascript"></script>
</head>
<body class="@context.settings.skinName page-load @if(body.toString.contains("menu-item-hover")){sidebar-mini} @if(context.sidebarCollapse){sidebar-collapse}">
<div class="wrapper">
<header class="main-header">
<a href="@context.path/" class="logo">
<img src="@helpers.assets("/common/images/gitbucket.svg")" style="width: 24px; height: 24px; display: inline;"/>
GitBucket
<span class="header-version">@gitbucket.core.GitBucketCoreModule.getVersions.last.getVersion</span>
<span class="logo-mini"><img src="@helpers.assets("/common/images/gitbucket.svg")" alt="GitBucket" /></span>
<span class="logo-lg"><img src="@helpers.assets("/common/images/gitbucket.svg")" alt="GitBucket" />
<span class="header-title strong">GitBucket</span>
<span class="header-version">@gitbucket.core.GitBucketCoreModule.getVersions.last.getVersion</span></span>
</a>
<nav class="navbar navbar-static-top" role="navigation">
<!-- Sidebar toggle button-->
@if(body.toString.contains("main-sidebar")){
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
<a href="#" class="sidebar-toggle" data-toggle="push-menu" role="button">
<span class="sr-only">Toggle navigation</span>
</a>
}
@@ -122,9 +124,11 @@
$('#search').submit(function(){
return $.trim($(this).find('input[name=query]').val()) != '';
});
$(".sidebar-toggle").on('click', function(e){
$.get('@context.path/sidebar-collapse', { collapse: !$('body').hasClass('sidebar-collapse') });
});
@if(body.toString.contains("main-sidebar")){
$(".sidebar-toggle").on('click', function(e){
$.post('@context.path/sidebar-collapse', { collapse: !$('body').hasClass('sidebar-collapse') });
});
}
});
</script>
@PluginRegistry().getJavaScript(context.request.getRequestURI).map { script =>

View File

@@ -7,11 +7,11 @@
isBlame: Boolean,
isLfsFile: Boolean)(implicit context: gitbucket.core.controller.Context)
@import gitbucket.core.view.helpers
@gitbucket.core.html.main(s"${(repository.name :: pathList).mkString("/")} at ${helpers.encodeRefName(branch)} - ${repository.owner}/${repository.name}", Some(repository)) {
@gitbucket.core.html.main(s"${(repository.name :: pathList).mkString("/")} at ${branch} - ${repository.owner}/${repository.name}", Some(repository)) {
@gitbucket.core.html.menu("files", repository){
<div class="head">
<div class="pull-right hide-if-blame"><div class="btn-group">
<a href="@helpers.url(repository)/blob/@latestCommit.id/@pathList.mkString("/")" data-hotkey="y" style="display: none;">Transfer to URL with SHA</a>
<a href="@helpers.url(repository)/blob/@helpers.encodeRefName((latestCommit.id :: pathList).mkString("/"))" data-hotkey="y" style="display: none;">Transfer to URL with SHA</a>
<a href="@helpers.url(repository)/find/@helpers.encodeRefName(branch)" class="btn btn-sm btn-default" data-hotkey="t">Find file</a>
</div></div>
<div class="line-age-legend">
@@ -31,13 +31,9 @@
<span>Older</span>
</div>
<div id="branchCtrlWrapper" style="display:inline;">
@gitbucket.core.helper.html.branchcontrol(
branch,
repository,
hasWritePermission
){
@gitbucket.core.helper.html.branchcontrol(branch, repository, hasWritePermission){
@repository.branchList.map { x =>
<li><a href="@helpers.url(repository)/blob/@helpers.encodeRefName(x)/@pathList.mkString("/")">@gitbucket.core.helper.html.checkicon(x == branch) @x</a></li>
<li><a href="@helpers.url(repository)/blob/@helpers.encodeRefName((x :: pathList).mkString("/"))">@gitbucket.core.helper.html.checkicon(x == branch) @x</a></li>
}
}
</div>
@@ -46,7 +42,7 @@
@if(i == pathList.length - 1){
@section
} else {
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)/@pathList.take(i + 1).mkString("/")">@section</a> /
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName((branch :: pathList.take(i + 1)).mkString("/"))">@section</a> /
}
}
@if(isLfsFile){
@@ -61,15 +57,16 @@
<a href="@helpers.url(repository)/commit/@latestCommit.id" class="commit-message">@helpers.link(latestCommit.summary, repository)</a>
<div class="btn-group pull-right">
@if(hasWritePermission && content.viewType == "text" && repository.branchList.contains(branch)){
<a class="btn btn-sm btn-default" href="@helpers.url(repository)/edit/@helpers.encodeRefName(branch)/@pathList.mkString("/")">Edit</a>
<a class="btn btn-sm btn-default" href="@helpers.url(repository)/edit/@helpers.encodeRefName((branch :: pathList).mkString("/"))">Edit</a>
}
<a class="btn btn-sm btn-default" href="@helpers.url(repository)/raw/@latestCommit.id/@pathList.mkString("/")">Raw</a>
<a class="btn btn-sm btn-default" href="@helpers.url(repository)/raw/@latestCommit.id/@helpers.encodeRefName(pathList.mkString("/"))">Raw</a>
@if(content.viewType == "text"){
<a class="btn btn-sm btn-default blame-action" href="@helpers.url(repository)/blame/@latestCommit.id/@pathList.mkString("/")" data-url="@helpers.url(repository)/get-blame/@latestCommit.id/@pathList.mkString("/")" data-repository="@helpers.url(repository)">Blame</a>
<a class="btn btn-sm btn-default blame-action" href="@helpers.url(repository)/blame/@latestCommit.id/@helpers.encodeRefName(pathList.mkString("/"))"
data-url="@helpers.url(repository)/get-blame/@helpers.encodeRefName((latestCommit.id :: pathList).mkString("/"))" data-repository="@helpers.url(repository)">Blame</a>
}
<a class="btn btn-sm btn-default" href="@helpers.url(repository)/commits/@helpers.encodeRefName(branch)/@pathList.mkString("/")">History</a>
<a class="btn btn-sm btn-default" href="@helpers.url(repository)/commits/@helpers.encodeRefName((branch :: pathList).mkString("/"))">History</a>
@if(hasWritePermission && repository.branchList.contains(branch)){
<a class="btn btn-sm btn-danger" href="@helpers.url(repository)/remove/@helpers.encodeRefName(branch)/@pathList.mkString("/")">Delete</a>
<a class="btn btn-sm btn-danger" href="@helpers.url(repository)/remove/@helpers.encodeRefName((branch :: pathList).mkString("/"))">Delete</a>
}
</div>
</div>
@@ -88,12 +85,12 @@
}
@if(content.viewType == "image"){
<div class="box-content-bottom">
<img src="@helpers.url(repository)/raw/@helpers.encodeRefName(branch)/@pathList.mkString("/")"/>
<img src="@helpers.url(repository)/raw/@helpers.encodeRefName((branch :: pathList).mkString("/"))"/>
</div>
}
@if(content.viewType == "large" || content.viewType == "binary"){
<div class="box-content-bottom" style="text-align: center; padding-top: 20px; padding-bottom: 20px;">
<a href="@helpers.url(repository)/raw/@helpers.encodeRefName(branch)/@pathList.mkString("/")">View Raw</a><br>
<a href="@helpers.url(repository)/raw/@helpers.encodeRefName((branch :: pathList).mkString("/"))">View Raw</a><br>
<br>
(Sorry about that, but we can't show files that are this big right now)
</div>
@@ -101,7 +98,7 @@
}
}
<script>
$(window).load(function(){
$(window).on('load', function(){
updateHighlighting();
window.onhashchange = function(){
@@ -133,7 +130,7 @@ $(window).load(function(){
}
var line = pos[i].id.replace(/^L/,'');
var hash = location.hash;
var commitUrl = '@helpers.url(repository)/blob/@latestCommit.id/@pathList.mkString("/")';
var commitUrl = '@helpers.url(repository)/blob/@helpers.encodeRefName((latestCommit.id :: pathList).mkString("/"))';
if(e.shiftKey == true && hash.match(/#L\d+(-L\d+)?/)){
var lines = hash.split('-');
window.history.pushState('', '', commitUrl + lines[0] + '-L' + line);
@@ -170,7 +167,7 @@ $(window).load(function(){
updateSourceLineNum();
return;
}
$(document.body).toggleClass('no-box-shadow', document.body.style.boxShadow===undefined);
$(document.body).toggleClass('no-box-shadow', document.body.style.boxShadow === undefined);
$('.blame-action').addClass("active");
var base = $('<div class="blame">').css({height: pre.height()}).prependTo(pre.parents("div.box-content-bottom"));
base.parent().addClass("blame-container");

View File

@@ -44,7 +44,7 @@
<script>
$('.btn-inline-comment').click(function(e) {
e.preventDefault();
$form = $(e.target).attr('disabled', 'disabled').closest('form');
var $form = $(e.target).attr('disabled', 'disabled').closest('form');
var param = {};
$($form.serializeArray()).each(function(i, v) {
param[v.name] = v.value;
@@ -64,7 +64,16 @@
} else {
tmp = '<td colspan="3" class="comment-box-container"></td>'
}
$form.closest('tr').removeClass('inline-comment-form').html(tmp).find('.comment-box-container').html(data);
var $tr = $form.closest('tr.not-diff');
// Apply comment
$tr.removeClass('inline-comment-form').html(tmp).find('.comment-box-container').html(data);
// Show reply comment form
var replyComment = $tr.prev().find('.reply-comment').closest('.not-diff').show();
replyComment.remove();
$tr.after(replyComment);
$('#comment-list').append(data);
if (typeof $('#show-notes')[0] !== 'undefined' && !$('#show-notes')[0].checked) {
$('#comment-list').children('.inline-comment').hide();

View File

@@ -12,11 +12,7 @@
@gitbucket.core.html.menu("files", repository){
<div class="head">
@if(pathList.isEmpty){
@gitbucket.core.helper.html.branchcontrol(
branch,
repository,
hasWritePermission
){
@gitbucket.core.helper.html.branchcontrol(branch, repository, hasWritePermission){
@repository.branchList.map { x =>
<li><a href="@helpers.url(repository)/commits/@helpers.encodeRefName(x)">@gitbucket.core.helper.html.checkicon(x == branch) @x</a></li>
}
@@ -29,7 +25,7 @@
@if(i == pathList.length - 1){
<span class="strong">@section</span>
} else {
<a class="strong" href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)/@pathList.take(i + 1).mkString("/")">@section</a> /
<a class="strong" href="@helpers.url(repository)/tree/@helpers.encodeRefName((branch :: pathList.take(i + 1)).mkString("/"))">@section</a> /
}
}
}

View File

@@ -12,7 +12,7 @@
<div class="head">
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)">@repository.name</a> /
@pathList.zipWithIndex.map { case (section, i) =>
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)/@pathList.take(i + 1).mkString("/")">@section</a> /
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName((branch :: pathList.take(i + 1)).mkString("/"))">@section</a> /
}
@fileName
<input type="hidden" name="fileName" id="fileName" value="@fileName"/>
@@ -25,7 +25,7 @@
<th style="font-weight: normal;" class="box-header">
<span class="monospace">@fileName</span>
<div class="pull-right align-right">
<a href="@helpers.url(repository)/blob/@branch/@{(pathList ::: List(fileName)).mkString("/")}" class="btn btn-default btn-sm">View</a>
<a href="@helpers.url(repository)/blob/@helpers.encodeRefName((branch :: pathList ::: List(fileName)).mkString("/"))" class="btn btn-default btn-sm">View</a>
</div>
</th>
</tr>
@@ -46,7 +46,7 @@
<input type="text" name="message" class="form-control"/>
</div>
<div style="text-align: right;">
<a href="@helpers.url(repository)/blob/@helpers.encodeRefName(branch)/@pathList.mkString("/")" class="btn btn-danger">Cancel</a>
<a href="@helpers.url(repository)/blob/@helpers.encodeRefName((branch :: pathList).mkString("/"))" class="btn btn-danger">Cancel</a>
<input type="submit" id="commitButton" class="btn btn-success" value="Commit changes"/>
</div>
</div>

View File

@@ -17,7 +17,7 @@
<div class="head">
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)">@repository.name</a> /
@pathList.zipWithIndex.map { case (section, i) =>
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)/@pathList.take(i + 1).mkString("/")">@section</a> /
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName((branch :: pathList.take(i + 1)).mkString("/"))">@section</a> /
}
<input type="text" name="newFileName" id="newFileName" class="form-control" placeholder="Name your file..." value="@fileName"/>
<input type="hidden" name="oldFileName" id="oldFileName" value="@fileName"/>
@@ -58,9 +58,9 @@
</div>
<div style="text-align: right;">
@if(fileName.isEmpty){
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)/@{pathList.mkString("/")}" class="btn btn-danger">Cancel</a>
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName((branch :: pathList).mkString("/"))" class="btn btn-danger">Cancel</a>
} else {
<a href="@helpers.url(repository)/blob/@helpers.encodeRefName(branch)/@{(pathList ++ Seq(fileName.get)).mkString("/")}" class="btn btn-danger">Cancel</a>
<a href="@helpers.url(repository)/blob/@helpers.encodeRefName((branch :: pathList ++ Seq(fileName.get)).mkString("/"))" class="btn btn-danger">Cancel</a>
}
<input type="submit" id="commitButton" class="btn btn-success" value="Commit changes" disabled="true"/>
<input type="hidden" id="charset" name="charset" value="@content.charset"/>

View File

@@ -16,25 +16,25 @@
if(branch == repository.repository.defaultBranch){
s"${repository.owner}/${repository.name}"
} else {
s"${repository.owner}/${repository.name} at ${helpers.encodeRefName(branch)}"
s"${repository.owner}/${repository.name} at ${branch}"
}
} else {
s"${(repository.name :: pathList).mkString("/")} at ${helpers.encodeRefName(branch)} - ${repository.owner}/${repository.name}"
s"${(repository.name :: pathList).mkString("/")} at ${branch} - ${repository.owner}/${repository.name}"
}, Some(repository)) {
@gitbucket.core.html.menu("files", repository, Some(branch), info, error){
@if(pathList.isEmpty) {
@repository.repository.description.map { description =>
<p class="pc" style="margin-bottom: 10px;">
<span class="normal muted">@Html(helpers.detectAndRenderLinks(description, repository))</span>
<span class="normal muted">@Html(helpers.decorateHtml(helpers.urlLink(description), repository))</span>
</p>
}
}
<div class="head" style="height: 24px;">
<div class="pull-right">
<div class="btn-group">
<a href="@helpers.url(repository)/tree/@latestCommit.id/@pathList.mkString("/")" data-hotkey="y" style="display: none;">Transfer to URL with SHA</a>
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName((latestCommit.id :: pathList).mkString("/"))" data-hotkey="y" style="display: none;">Transfer to URL with SHA</a>
<a href="@helpers.url(repository)/find/@helpers.encodeRefName(branch)" class="btn btn-sm btn-default" data-hotkey="t"><i class="octicon octicon-search"></i></a>
<a href="@helpers.url(repository)/commits/@helpers.encodeRefName(branch)/@pathList.mkString("/")" class="btn btn-sm btn-default"><i class="octicon octicon-history"></i> @if(commitCount > 10000){10000+} else {@commitCount} @helpers.plural(commitCount, "commit")</a>
<a href="@helpers.url(repository)/commits/@helpers.encodeRefName((branch :: pathList).mkString("/"))" class="btn btn-sm btn-default"><i class="octicon octicon-history"></i> @if(commitCount > 10000){10000+} else {@commitCount} @helpers.plural(commitCount, "commit")</a>
</div>
</div>
@if(pathList.isEmpty){
@@ -84,14 +84,14 @@
@if(pathList.nonEmpty){
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)">@repository.name</a> /
@pathList.zipWithIndex.map { case (section, i) =>
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)/@pathList.take(i + 1).mkString("/")">@section</a> /
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName((branch :: pathList.take(i + 1)).mkString("/"))">@section</a> /
}
}
</div>
@if(hasWritePermission){
<div class="btn-group pull-left" style="margin-left: 4px;">
<a href="@helpers.url(repository)/new/@helpers.encodeRefName(branch)/@pathList.mkString("/")" class="btn btn-sm btn-default pc" title="Create a new file"><i class="octicon octicon-plus"></i></a>
<a href="@helpers.url(repository)/upload/@helpers.encodeRefName(branch)/@pathList.mkString("/")" class="btn btn-sm btn-default pc" title="Upload files"><i class="octicon octicon-cloud-upload"></i></a>
<a href="@helpers.url(repository)/new/@helpers.encodeRefName((branch :: pathList).mkString("/"))" class="btn btn-sm btn-default pc" title="Create a new file"><i class="octicon octicon-plus"></i></a>
<a href="@helpers.url(repository)/upload/@helpers.encodeRefName((branch :: pathList).mkString("/"))" class="btn btn-sm btn-default pc" title="Upload files"><i class="octicon octicon-cloud-upload"></i></a>
</div>
}
</div>
@@ -133,7 +133,7 @@
@if(pathList.size > 0){
<tr>
<td width="16" class="file-icon"></td>
<td><a href="@helpers.url(repository)@if(pathList.size > 1){/tree/@helpers.encodeRefName(branch)/@pathList.init.mkString("/")}">..</a></td>
<td><a href="@helpers.url(repository)@if(pathList.size > 1){/tree/@helpers.encodeRefName(branch)/@helpers.encodeRefName(pathList.init.mkString("/"))}">..</a></td>
<td></td>
<td></td>
</tr>
@@ -173,7 +173,7 @@
</span>
}
case None => {
<a href={helpers.url(repository) + "/tree" + (branch :: pathList).map(helpers.encodeRefName).mkString("/", "/", "/") + helpers.encodeRefName(file.name)}>
<a href={helpers.url(repository) + "/tree" + helpers.encodeRefName((branch :: pathList).mkString("/", "/", "/") + file.name)}>
<span class="simplified-path">{file.name.split("/").toList.init match {
case Nil => ""
case list => list.mkString("", "/", "/")
@@ -183,7 +183,7 @@
}
}}
} else {
<a href="@helpers.url(repository)/blob@{(branch :: pathList).map(helpers.encodeRefName).mkString("/", "/", "/")}@{helpers.encodeRefName(file.name)}">@file.name</a>
<a href="@helpers.url(repository)/blob@{helpers.encodeRefName((branch :: pathList).mkString("/", "/", "/") + file.name)}">@file.name</a>
}
</td>
<td class="ellipsis-cell" style="width: 70%;">

View File

@@ -59,19 +59,19 @@ $(function(){
if(e.keyCode == 40){ // DOWN
e.preventDefault();
e.stopPropagation();
changeCursor(cursor+1);
}else if(e.keyCode==38){ // UP
changeCursor(cursor + 1);
}else if(e.keyCode == 38){ // UP
e.preventDefault();
e.stopPropagation();
changeCursor(cursor-1);
}else if(e.keyCode==13){ // ENTER
changeCursor(cursor - 1);
}else if(e.keyCode == 13){ // ENTER
e.preventDefault();
e.stopPropagation();
target = $(".tree-browser-result.navigation-focus a");
if(target[0]){
target[0].click();
}
}else if(e.keyCode==27){ // ESC
}else if(e.keyCode == 27){ // ESC
e.preventDefault();
e.stopPropagation();
history.back();
@@ -90,23 +90,25 @@ $(function(){
}
function filter(){
var v = $('#tree-finder-field').val();
if(v==preKeyword || paths.length==0){
if(v == preKeyword || paths.length == 0){
return;
}
scrollIntoView('#tree-finder-field');
preKeyword=v;
cursor=0;
preKeyword = v;
cursor = 0;
var p = string_score_sort(v, paths, 50);
res.html("");
if(p.length==0){
if(p.length == 0){
$(".no-results").show();
return;
}else{
$(".no-results").hide();
for(var i=0;i < p.length;i++){
for(var i = 0; i < p.length; i++){
var row = template.clone();
row.find("a").attr("href",pathBase+"/"+p[i].string).html(string_score_highlight(p[i], '<b>'));
if(cursor==i){
// console.log('Path base: ' + pathBase);
// console.log('Path rest ' + p[i].string);
row.find("a").attr("href", pathBase + "/" + encodeURIComponent(p[i].string).replace('%2F', '/')).html(string_score_highlight(p[i], '<b>'));
if(cursor == i){
row.addClass("navigation-focus");
}
row.appendTo(res);
@@ -116,4 +118,4 @@ $(function(){
});
</script>
}
}
}

View File

@@ -13,7 +13,7 @@
<div class="head">
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)">@repository.name</a> /
@pathList.zipWithIndex.map { case (section, i) =>
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)/@pathList.take(i + 1).mkString("/")">@section</a> /
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch + "/" + pathList.take(i + 1).mkString("/"))">@section</a> /
}
<input type="hidden" name="branch" id="branch" value="@branch"/>
<input type="hidden" name="path" id="path" value="@pathList.mkString("/")"/>
@@ -38,7 +38,7 @@
<input type="text" name="message" class="form-control"/>
</div>
<div style="text-align: right;">
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)/@{pathList.mkString("/")}" class="btn btn-danger">Cancel</a>
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch + "/" + pathList.mkString("/"))" class="btn btn-danger">Cancel</a>
<input type="submit" id="commit" class="btn btn-success" value="Commit changes" disabled="true"/>
<input type="hidden" id="upload-files-data" name="uploadFiles" value=""/>
</div>

View File

@@ -26,7 +26,7 @@
<input type="text" value="@webHook.url" class="form-control" style="display: inline; width: 500px; vertical-align: middle;" disabled />
<input type="hidden" value="@webHook.url" name="url" />
}
<button class="btn btn-default" id="test">Test Hook</button>
<button class="btn btn-default" id="test-hook">Test Hook</button>
</fieldset>
<fieldset class="form-group">
<label class="strong">Content type</label>
@@ -131,7 +131,7 @@ $(function(){
e.preventDefault();
$(this).tab('show');
});
$('#test').click(function(e){
$('#test-hook').click(function(e){
e.stopPropagation();
e.stopImmediatePropagation();
e.preventDefault();

View File

@@ -131,6 +131,12 @@ span.header-version {
font-size: small;
}
.main-header .logo img {
width: 24px;
height: 24px;
display: inline;
}
/* ======================================================================== */
/* General Styles */
/* ======================================================================== */
@@ -151,11 +157,6 @@ div.container {
padding-right: 10px;
}
div.container-wide {
padding-left: 10px;
padding-right: 10px;
}
div.main-center {
margin: 0 auto;
}
@@ -583,6 +584,11 @@ pre.blob {
font-size: 12px;
}
div.markdown-body pre.plain {
background: white;
font-size: 14px;
}
#readme {
margin-top: 20px;
}
@@ -1161,7 +1167,8 @@ table.diff tbody tr.not-diff:hover td {
.not-diff > .comment-box-container {
white-space: normal;
line-height: initial;
padding: 10px;
padding-left: 10px;
padding-right: 10px;
}
.diff .oldline:before, .diff .newline:before {

File diff suppressed because one or more lines are too long

View File

@@ -1,760 +0,0 @@
/*
* Social Buttons for Bootstrap
*
* Copyright 2013-2015 Panayiotis Lipiridis
* Licensed under the MIT License
*
* https://github.com/lipis/bootstrap-social
*/
.btn-social {
position: relative;
padding-left: 44px;
text-align: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.btn-social > :first-child {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 32px;
line-height: 34px;
font-size: 1.6em;
text-align: center;
border-right: 1px solid rgba(0, 0, 0, 0.2);
}
.btn-social.btn-lg {
padding-left: 61px;
}
.btn-social.btn-lg > :first-child {
line-height: 45px;
width: 45px;
font-size: 1.8em;
}
.btn-social.btn-sm {
padding-left: 38px;
}
.btn-social.btn-sm > :first-child {
line-height: 28px;
width: 28px;
font-size: 1.4em;
}
.btn-social.btn-xs {
padding-left: 30px;
}
.btn-social.btn-xs > :first-child {
line-height: 20px;
width: 20px;
font-size: 1.2em;
}
.btn-social-icon {
position: relative;
padding-left: 44px;
text-align: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
height: 34px;
width: 34px;
padding: 0;
}
.btn-social-icon > :first-child {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 32px;
line-height: 34px;
font-size: 1.6em;
text-align: center;
border-right: 1px solid rgba(0, 0, 0, 0.2);
}
.btn-social-icon.btn-lg {
padding-left: 61px;
}
.btn-social-icon.btn-lg > :first-child {
line-height: 45px;
width: 45px;
font-size: 1.8em;
}
.btn-social-icon.btn-sm {
padding-left: 38px;
}
.btn-social-icon.btn-sm > :first-child {
line-height: 28px;
width: 28px;
font-size: 1.4em;
}
.btn-social-icon.btn-xs {
padding-left: 30px;
}
.btn-social-icon.btn-xs > :first-child {
line-height: 20px;
width: 20px;
font-size: 1.2em;
}
.btn-social-icon > :first-child {
border: none;
text-align: center;
width: 100%;
}
.btn-social-icon.btn-lg {
height: 45px;
width: 45px;
padding-left: 0;
padding-right: 0;
}
.btn-social-icon.btn-sm {
height: 30px;
width: 30px;
padding-left: 0;
padding-right: 0;
}
.btn-social-icon.btn-xs {
height: 22px;
width: 22px;
padding-left: 0;
padding-right: 0;
}
.btn-adn {
color: #ffffff;
background-color: #d87a68;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-adn:focus,
.btn-adn.focus {
color: #ffffff;
background-color: #ce563f;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-adn:hover {
color: #ffffff;
background-color: #ce563f;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-adn:active,
.btn-adn.active,
.open > .dropdown-toggle.btn-adn {
color: #ffffff;
background-color: #ce563f;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-adn:active,
.btn-adn.active,
.open > .dropdown-toggle.btn-adn {
background-image: none;
}
.btn-adn .badge {
color: #d87a68;
background-color: #ffffff;
}
.btn-bitbucket {
color: #ffffff;
background-color: #205081;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-bitbucket:focus,
.btn-bitbucket.focus {
color: #ffffff;
background-color: #163758;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-bitbucket:hover {
color: #ffffff;
background-color: #163758;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-bitbucket:active,
.btn-bitbucket.active,
.open > .dropdown-toggle.btn-bitbucket {
color: #ffffff;
background-color: #163758;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-bitbucket:active,
.btn-bitbucket.active,
.open > .dropdown-toggle.btn-bitbucket {
background-image: none;
}
.btn-bitbucket .badge {
color: #205081;
background-color: #ffffff;
}
.btn-dropbox {
color: #ffffff;
background-color: #1087dd;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-dropbox:focus,
.btn-dropbox.focus {
color: #ffffff;
background-color: #0d6aad;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-dropbox:hover {
color: #ffffff;
background-color: #0d6aad;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-dropbox:active,
.btn-dropbox.active,
.open > .dropdown-toggle.btn-dropbox {
color: #ffffff;
background-color: #0d6aad;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-dropbox:active,
.btn-dropbox.active,
.open > .dropdown-toggle.btn-dropbox {
background-image: none;
}
.btn-dropbox .badge {
color: #1087dd;
background-color: #ffffff;
}
.btn-facebook {
color: #ffffff;
background-color: #3b5998;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-facebook:focus,
.btn-facebook.focus {
color: #ffffff;
background-color: #2d4373;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-facebook:hover {
color: #ffffff;
background-color: #2d4373;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-facebook:active,
.btn-facebook.active,
.open > .dropdown-toggle.btn-facebook {
color: #ffffff;
background-color: #2d4373;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-facebook:active,
.btn-facebook.active,
.open > .dropdown-toggle.btn-facebook {
background-image: none;
}
.btn-facebook .badge {
color: #3b5998;
background-color: #ffffff;
}
.btn-flickr {
color: #ffffff;
background-color: #ff0084;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-flickr:focus,
.btn-flickr.focus {
color: #ffffff;
background-color: #cc006a;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-flickr:hover {
color: #ffffff;
background-color: #cc006a;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-flickr:active,
.btn-flickr.active,
.open > .dropdown-toggle.btn-flickr {
color: #ffffff;
background-color: #cc006a;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-flickr:active,
.btn-flickr.active,
.open > .dropdown-toggle.btn-flickr {
background-image: none;
}
.btn-flickr .badge {
color: #ff0084;
background-color: #ffffff;
}
.btn-foursquare {
color: #ffffff;
background-color: #f94877;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-foursquare:focus,
.btn-foursquare.focus {
color: #ffffff;
background-color: #f71752;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-foursquare:hover {
color: #ffffff;
background-color: #f71752;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-foursquare:active,
.btn-foursquare.active,
.open > .dropdown-toggle.btn-foursquare {
color: #ffffff;
background-color: #f71752;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-foursquare:active,
.btn-foursquare.active,
.open > .dropdown-toggle.btn-foursquare {
background-image: none;
}
.btn-foursquare .badge {
color: #f94877;
background-color: #ffffff;
}
.btn-github {
color: #ffffff;
background-color: #444444;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-github:focus,
.btn-github.focus {
color: #ffffff;
background-color: #2b2b2b;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-github:hover {
color: #ffffff;
background-color: #2b2b2b;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-github:active,
.btn-github.active,
.open > .dropdown-toggle.btn-github {
color: #ffffff;
background-color: #2b2b2b;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-github:active,
.btn-github.active,
.open > .dropdown-toggle.btn-github {
background-image: none;
}
.btn-github .badge {
color: #444444;
background-color: #ffffff;
}
.btn-google {
color: #ffffff;
background-color: #dd4b39;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-google:focus,
.btn-google.focus {
color: #ffffff;
background-color: #c23321;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-google:hover {
color: #ffffff;
background-color: #c23321;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-google:active,
.btn-google.active,
.open > .dropdown-toggle.btn-google {
color: #ffffff;
background-color: #c23321;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-google:active,
.btn-google.active,
.open > .dropdown-toggle.btn-google {
background-image: none;
}
.btn-google .badge {
color: #dd4b39;
background-color: #ffffff;
}
.btn-instagram {
color: #ffffff;
background-color: #3f729b;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-instagram:focus,
.btn-instagram.focus {
color: #ffffff;
background-color: #305777;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-instagram:hover {
color: #ffffff;
background-color: #305777;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-instagram:active,
.btn-instagram.active,
.open > .dropdown-toggle.btn-instagram {
color: #ffffff;
background-color: #305777;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-instagram:active,
.btn-instagram.active,
.open > .dropdown-toggle.btn-instagram {
background-image: none;
}
.btn-instagram .badge {
color: #3f729b;
background-color: #ffffff;
}
.btn-linkedin {
color: #ffffff;
background-color: #007bb6;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-linkedin:focus,
.btn-linkedin.focus {
color: #ffffff;
background-color: #005983;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-linkedin:hover {
color: #ffffff;
background-color: #005983;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-linkedin:active,
.btn-linkedin.active,
.open > .dropdown-toggle.btn-linkedin {
color: #ffffff;
background-color: #005983;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-linkedin:active,
.btn-linkedin.active,
.open > .dropdown-toggle.btn-linkedin {
background-image: none;
}
.btn-linkedin .badge {
color: #007bb6;
background-color: #ffffff;
}
.btn-microsoft {
color: #ffffff;
background-color: #2672ec;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-microsoft:focus,
.btn-microsoft.focus {
color: #ffffff;
background-color: #125acd;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-microsoft:hover {
color: #ffffff;
background-color: #125acd;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-microsoft:active,
.btn-microsoft.active,
.open > .dropdown-toggle.btn-microsoft {
color: #ffffff;
background-color: #125acd;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-microsoft:active,
.btn-microsoft.active,
.open > .dropdown-toggle.btn-microsoft {
background-image: none;
}
.btn-microsoft .badge {
color: #2672ec;
background-color: #ffffff;
}
.btn-openid {
color: #ffffff;
background-color: #f7931e;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-openid:focus,
.btn-openid.focus {
color: #ffffff;
background-color: #da7908;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-openid:hover {
color: #ffffff;
background-color: #da7908;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-openid:active,
.btn-openid.active,
.open > .dropdown-toggle.btn-openid {
color: #ffffff;
background-color: #da7908;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-openid:active,
.btn-openid.active,
.open > .dropdown-toggle.btn-openid {
background-image: none;
}
.btn-openid .badge {
color: #f7931e;
background-color: #ffffff;
}
.btn-pinterest {
color: #ffffff;
background-color: #cb2027;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-pinterest:focus,
.btn-pinterest.focus {
color: #ffffff;
background-color: #9f191f;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-pinterest:hover {
color: #ffffff;
background-color: #9f191f;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-pinterest:active,
.btn-pinterest.active,
.open > .dropdown-toggle.btn-pinterest {
color: #ffffff;
background-color: #9f191f;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-pinterest:active,
.btn-pinterest.active,
.open > .dropdown-toggle.btn-pinterest {
background-image: none;
}
.btn-pinterest .badge {
color: #cb2027;
background-color: #ffffff;
}
.btn-reddit {
color: #000000;
background-color: #eff7ff;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-reddit:focus,
.btn-reddit.focus {
color: #000000;
background-color: #bcddff;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-reddit:hover {
color: #000000;
background-color: #bcddff;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-reddit:active,
.btn-reddit.active,
.open > .dropdown-toggle.btn-reddit {
color: #000000;
background-color: #bcddff;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-reddit:active,
.btn-reddit.active,
.open > .dropdown-toggle.btn-reddit {
background-image: none;
}
.btn-reddit .badge {
color: #eff7ff;
background-color: #000000;
}
.btn-soundcloud {
color: #ffffff;
background-color: #ff5500;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-soundcloud:focus,
.btn-soundcloud.focus {
color: #ffffff;
background-color: #cc4400;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-soundcloud:hover {
color: #ffffff;
background-color: #cc4400;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-soundcloud:active,
.btn-soundcloud.active,
.open > .dropdown-toggle.btn-soundcloud {
color: #ffffff;
background-color: #cc4400;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-soundcloud:active,
.btn-soundcloud.active,
.open > .dropdown-toggle.btn-soundcloud {
background-image: none;
}
.btn-soundcloud .badge {
color: #ff5500;
background-color: #ffffff;
}
.btn-tumblr {
color: #ffffff;
background-color: #2c4762;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-tumblr:focus,
.btn-tumblr.focus {
color: #ffffff;
background-color: #1c2d3f;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-tumblr:hover {
color: #ffffff;
background-color: #1c2d3f;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-tumblr:active,
.btn-tumblr.active,
.open > .dropdown-toggle.btn-tumblr {
color: #ffffff;
background-color: #1c2d3f;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-tumblr:active,
.btn-tumblr.active,
.open > .dropdown-toggle.btn-tumblr {
background-image: none;
}
.btn-tumblr .badge {
color: #2c4762;
background-color: #ffffff;
}
.btn-twitter {
color: #ffffff;
background-color: #55acee;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-twitter:focus,
.btn-twitter.focus {
color: #ffffff;
background-color: #2795e9;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-twitter:hover {
color: #ffffff;
background-color: #2795e9;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-twitter:active,
.btn-twitter.active,
.open > .dropdown-toggle.btn-twitter {
color: #ffffff;
background-color: #2795e9;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-twitter:active,
.btn-twitter.active,
.open > .dropdown-toggle.btn-twitter {
background-image: none;
}
.btn-twitter .badge {
color: #55acee;
background-color: #ffffff;
}
.btn-vimeo {
color: #ffffff;
background-color: #1ab7ea;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-vimeo:focus,
.btn-vimeo.focus {
color: #ffffff;
background-color: #1295bf;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-vimeo:hover {
color: #ffffff;
background-color: #1295bf;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-vimeo:active,
.btn-vimeo.active,
.open > .dropdown-toggle.btn-vimeo {
color: #ffffff;
background-color: #1295bf;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-vimeo:active,
.btn-vimeo.active,
.open > .dropdown-toggle.btn-vimeo {
background-image: none;
}
.btn-vimeo .badge {
color: #1ab7ea;
background-color: #ffffff;
}
.btn-vk {
color: #ffffff;
background-color: #587ea3;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-vk:focus,
.btn-vk.focus {
color: #ffffff;
background-color: #466482;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-vk:hover {
color: #ffffff;
background-color: #466482;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-vk:active,
.btn-vk.active,
.open > .dropdown-toggle.btn-vk {
color: #ffffff;
background-color: #466482;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-vk:active,
.btn-vk.active,
.open > .dropdown-toggle.btn-vk {
background-image: none;
}
.btn-vk .badge {
color: #587ea3;
background-color: #ffffff;
}
.btn-yahoo {
color: #ffffff;
background-color: #720e9e;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-yahoo:focus,
.btn-yahoo.focus {
color: #ffffff;
background-color: #500a6f;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-yahoo:hover {
color: #ffffff;
background-color: #500a6f;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-yahoo:active,
.btn-yahoo.active,
.open > .dropdown-toggle.btn-yahoo {
color: #ffffff;
background-color: #500a6f;
border-color: rgba(0, 0, 0, 0.2);
}
.btn-yahoo:active,
.btn-yahoo.active,
.open > .dropdown-toggle.btn-yahoo {
background-image: none;
}
.btn-yahoo .badge {
color: #720e9e;
background-color: #ffffff;
}

File diff suppressed because one or more lines are too long

View File

@@ -1,93 +0,0 @@
/*
* Plugin: Full Calendar
* ---------------------
*/
.fc-button {
background: #f4f4f4;
background-image: none;
color: #444;
border-color: #ddd;
border-bottom-color: #ddd;
}
.fc-button:hover,
.fc-button:active,
.fc-button.hover {
background-color: #e9e9e9;
}
.fc-header-title h2 {
font-size: 15px;
line-height: 1.6em;
color: #666;
margin-left: 10px;
}
.fc-header-right {
padding-right: 10px;
}
.fc-header-left {
padding-left: 10px;
}
.fc-widget-header {
background: #fafafa;
}
.fc-grid {
width: 100%;
border: 0;
}
.fc-widget-header:first-of-type,
.fc-widget-content:first-of-type {
border-left: 0;
border-right: 0;
}
.fc-widget-header:last-of-type,
.fc-widget-content:last-of-type {
border-right: 0;
}
.fc-toolbar {
padding: 10px;
margin: 0;
}
.fc-day-number {
font-size: 20px;
font-weight: 300;
padding-right: 10px;
}
.fc-color-picker {
list-style: none;
margin: 0;
padding: 0;
}
.fc-color-picker > li {
float: left;
font-size: 30px;
margin-right: 5px;
line-height: 30px;
}
.fc-color-picker > li .fa {
-webkit-transition: -webkit-transform linear 0.3s;
-moz-transition: -moz-transform linear 0.3s;
-o-transition: -o-transform linear 0.3s;
transition: transform linear 0.3s;
}
.fc-color-picker > li .fa:hover {
-webkit-transform: rotate(30deg);
-ms-transform: rotate(30deg);
-o-transform: rotate(30deg);
transform: rotate(30deg);
}
#add-new-event {
-webkit-transition: all linear 0.3s;
-o-transition: all linear 0.3s;
transition: all linear 0.3s;
}
.external-event {
padding: 5px 10px;
font-weight: bold;
margin-bottom: 4px;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
border-radius: 3px;
cursor: move;
}
.external-event:hover {
box-shadow: inset 0 0 90px rgba(0, 0, 0, 0.2);
}

View File

@@ -1 +0,0 @@
.fc-button{background:#f4f4f4;background-image:none;color:#444;border-color:#ddd;border-bottom-color:#ddd}.fc-button:hover,.fc-button:active,.fc-button.hover{background-color:#e9e9e9}.fc-header-title h2{font-size:15px;line-height:1.6em;color:#666;margin-left:10px}.fc-header-right{padding-right:10px}.fc-header-left{padding-left:10px}.fc-widget-header{background:#fafafa}.fc-grid{width:100%;border:0}.fc-widget-header:first-of-type,.fc-widget-content:first-of-type{border-left:0;border-right:0}.fc-widget-header:last-of-type,.fc-widget-content:last-of-type{border-right:0}.fc-toolbar{padding:10px;margin:0}.fc-day-number{font-size:20px;font-weight:300;padding-right:10px}.fc-color-picker{list-style:none;margin:0;padding:0}.fc-color-picker>li{float:left;font-size:30px;margin-right:5px;line-height:30px}.fc-color-picker>li .fa{-webkit-transition:-webkit-transform linear .3s;-moz-transition:-moz-transform linear .3s;-o-transition:-o-transform linear .3s;transition:transform linear .3s}.fc-color-picker>li .fa:hover{-webkit-transform:rotate(30deg);-ms-transform:rotate(30deg);-o-transform:rotate(30deg);transform:rotate(30deg)}#add-new-event{-webkit-transition:all linear .3s;-o-transition:all linear .3s;transition:all linear .3s}.external-event{padding:5px 10px;font-weight:bold;margin-bottom:4px;box-shadow:0 1px 1px rgba(0,0,0,0.1);text-shadow:0 1px 1px rgba(0,0,0,0.1);border-radius:3px;cursor:move}.external-event:hover{box-shadow:inset 0 0 90px rgba(0,0,0,0.2)}

View File

@@ -1,97 +0,0 @@
/*
* Plugin: Select2
* ---------------
*/
.select2-container--default.select2-container--focus,
.select2-selection.select2-container--focus,
.select2-container--default:focus,
.select2-selection:focus,
.select2-container--default:active,
.select2-selection:active {
outline: none;
}
.select2-container--default .select2-selection--single,
.select2-selection .select2-selection--single {
border: 1px solid #d2d6de;
border-radius: 0;
padding: 6px 12px;
height: 34px;
}
.select2-container--default.select2-container--open {
border-color: #3c8dbc;
}
.select2-dropdown {
border: 1px solid #d2d6de;
border-radius: 0;
}
.select2-container--default .select2-results__option--highlighted[aria-selected] {
background-color: #3c8dbc;
color: white;
}
.select2-results__option {
padding: 6px 12px;
user-select: none;
-webkit-user-select: none;
}
.select2-container .select2-selection--single .select2-selection__rendered {
padding-left: 0;
padding-right: 0;
height: auto;
margin-top: -4px;
}
.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered {
padding-right: 6px;
padding-left: 20px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 28px;
right: 3px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
margin-top: 0;
}
.select2-dropdown .select2-search__field,
.select2-search--inline .select2-search__field {
border: 1px solid #d2d6de;
}
.select2-dropdown .select2-search__field:focus,
.select2-search--inline .select2-search__field:focus {
outline: none;
border: 1px solid #3c8dbc;
}
.select2-container--default .select2-results__option[aria-disabled=true] {
color: #999;
}
.select2-container--default .select2-results__option[aria-selected=true] {
background-color: #ddd;
}
.select2-container--default .select2-results__option[aria-selected=true],
.select2-container--default .select2-results__option[aria-selected=true]:hover {
color: #444;
}
.select2-container--default .select2-selection--multiple {
border: 1px solid #d2d6de;
border-radius: 0;
}
.select2-container--default .select2-selection--multiple:focus {
border-color: #3c8dbc;
}
.select2-container--default.select2-container--focus .select2-selection--multiple {
border-color: #d2d6de;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background-color: #3c8dbc;
border-color: #367fa9;
padding: 1px 10px;
color: #fff;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
margin-right: 5px;
color: rgba(255, 255, 255, 0.7);
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
color: #fff;
}
.select2-container .select2-selection--single .select2-selection__rendered {
padding-right: 10px;
}

View File

@@ -1 +0,0 @@
.select2-container--default.select2-container--focus,.select2-selection.select2-container--focus,.select2-container--default:focus,.select2-selection:focus,.select2-container--default:active,.select2-selection:active{outline:none}.select2-container--default .select2-selection--single,.select2-selection .select2-selection--single{border:1px solid #d2d6de;border-radius:0;padding:6px 12px;height:34px}.select2-container--default.select2-container--open{border-color:#3c8dbc}.select2-dropdown{border:1px solid #d2d6de;border-radius:0}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#3c8dbc;color:white}.select2-results__option{padding:6px 12px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{padding-left:0;padding-right:0;height:auto;margin-top:-4px}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:6px;padding-left:20px}.select2-container--default .select2-selection--single .select2-selection__arrow{height:28px;right:3px}.select2-container--default .select2-selection--single .select2-selection__arrow b{margin-top:0}.select2-dropdown .select2-search__field,.select2-search--inline .select2-search__field{border:1px solid #d2d6de}.select2-dropdown .select2-search__field:focus,.select2-search--inline .select2-search__field:focus{outline:none;border:1px solid #3c8dbc}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option[aria-selected=true],.select2-container--default .select2-results__option[aria-selected=true]:hover{color:#444}.select2-container--default .select2-selection--multiple{border:1px solid #d2d6de;border-radius:0}.select2-container--default .select2-selection--multiple:focus{border-color:#3c8dbc}.select2-container--default.select2-container--focus .select2-selection--multiple{border-color:#d2d6de}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#3c8dbc;border-color:#367fa9;padding:1px 10px;color:#fff}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{margin-right:5px;color:rgba(255,255,255,0.7)}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#fff}.select2-container .select2-selection--single .select2-selection__rendered{padding-right:10px}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
.skin-black-light .main-header{-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.skin-black-light .main-header .navbar-toggle{color:#333}.skin-black-light .main-header .navbar-brand{color:#333;border-right:1px solid #eee}.skin-black-light .main-header .navbar{background-color:#fff}.skin-black-light .main-header .navbar .nav>li>a{color:#333}.skin-black-light .main-header .navbar .nav>li>a:hover,.skin-black-light .main-header .navbar .nav>li>a:active,.skin-black-light .main-header .navbar .nav>li>a:focus,.skin-black-light .main-header .navbar .nav .open>a,.skin-black-light .main-header .navbar .nav .open>a:hover,.skin-black-light .main-header .navbar .nav .open>a:focus,.skin-black-light .main-header .navbar .nav>.active>a{background:#fff;color:#999}.skin-black-light .main-header .navbar .sidebar-toggle{color:#333}.skin-black-light .main-header .navbar .sidebar-toggle:hover{color:#999;background:#fff}.skin-black-light .main-header .navbar>.sidebar-toggle{color:#333;border-right:1px solid #eee}.skin-black-light .main-header .navbar .navbar-nav>li>a{border-right:1px solid #eee}.skin-black-light .main-header .navbar .navbar-custom-menu .navbar-nav>li>a,.skin-black-light .main-header .navbar .navbar-right>li>a{border-left:1px solid #eee;border-right-width:0}.skin-black-light .main-header>.logo{background-color:#fff;color:#333;border-bottom:0 solid transparent;border-right:1px solid #eee}.skin-black-light .main-header>.logo:hover{background-color:#fcfcfc}@media (max-width:767px){.skin-black-light .main-header>.logo{background-color:#222;color:#fff;border-bottom:0 solid transparent;border-right:none}.skin-black-light .main-header>.logo:hover{background-color:#1f1f1f}}.skin-black-light .main-header li.user-header{background-color:#222}.skin-black-light .content-header{background:transparent;box-shadow:none}.skin-black-light .wrapper,.skin-black-light .main-sidebar,.skin-black-light .left-side{background-color:#f9fafc}.skin-black-light .content-wrapper,.skin-black-light .main-footer{border-left:1px solid #d2d6de}.skin-black-light .user-panel>.info,.skin-black-light .user-panel>.info>a{color:#444}.skin-black-light .sidebar-menu>li{-webkit-transition:border-left-color .3s ease;-o-transition:border-left-color .3s ease;transition:border-left-color .3s ease}.skin-black-light .sidebar-menu>li.header{color:#848484;background:#f9fafc}.skin-black-light .sidebar-menu>li>a{border-left:3px solid transparent;font-weight:600}.skin-black-light .sidebar-menu>li:hover>a,.skin-black-light .sidebar-menu>li.active>a{color:#000;background:#f4f4f5}.skin-black-light .sidebar-menu>li.active{border-left-color:#fff}.skin-black-light .sidebar-menu>li.active>a{font-weight:600}.skin-black-light .sidebar-menu>li>.treeview-menu{background:#f4f4f5}.skin-black-light .sidebar a{color:#444}.skin-black-light .sidebar a:hover{text-decoration:none}.skin-black-light .treeview-menu>li>a{color:#777}.skin-black-light .treeview-menu>li.active>a,.skin-black-light .treeview-menu>li>a:hover{color:#000}.skin-black-light .treeview-menu>li.active>a{font-weight:600}.skin-black-light .sidebar-form{border-radius:3px;border:1px solid #d2d6de;margin:10px 10px}.skin-black-light .sidebar-form input[type="text"],.skin-black-light .sidebar-form .btn{box-shadow:none;background-color:#fff;border:1px solid transparent;height:35px}.skin-black-light .sidebar-form input[type="text"]{color:#666;border-top-left-radius:2px;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:2px}.skin-black-light .sidebar-form input[type="text"]:focus,.skin-black-light .sidebar-form input[type="text"]:focus+.input-group-btn .btn{background-color:#fff;color:#666}.skin-black-light .sidebar-form input[type="text"]:focus+.input-group-btn .btn{border-left-color:#fff}.skin-black-light .sidebar-form .btn{color:#999;border-top-left-radius:0;border-top-right-radius:2px;border-bottom-right-radius:2px;border-bottom-left-radius:0}@media (min-width:768px){.skin-black-light.sidebar-mini.sidebar-collapse .sidebar-menu>li>.treeview-menu{border-left:1px solid #d2d6de}}

View File

@@ -1 +0,0 @@
.skin-blue-light .main-header .navbar{background-color:#3c8dbc}.skin-blue-light .main-header .navbar .nav>li>a{color:#fff}.skin-blue-light .main-header .navbar .nav>li>a:hover,.skin-blue-light .main-header .navbar .nav>li>a:active,.skin-blue-light .main-header .navbar .nav>li>a:focus,.skin-blue-light .main-header .navbar .nav .open>a,.skin-blue-light .main-header .navbar .nav .open>a:hover,.skin-blue-light .main-header .navbar .nav .open>a:focus,.skin-blue-light .main-header .navbar .nav>.active>a{background:rgba(0,0,0,0.1);color:#f6f6f6}.skin-blue-light .main-header .navbar .sidebar-toggle{color:#fff}.skin-blue-light .main-header .navbar .sidebar-toggle:hover{color:#f6f6f6;background:rgba(0,0,0,0.1)}.skin-blue-light .main-header .navbar .sidebar-toggle{color:#fff}.skin-blue-light .main-header .navbar .sidebar-toggle:hover{background-color:#367fa9}@media (max-width:767px){.skin-blue-light .main-header .navbar .dropdown-menu li.divider{background-color:rgba(255,255,255,0.1)}.skin-blue-light .main-header .navbar .dropdown-menu li a{color:#fff}.skin-blue-light .main-header .navbar .dropdown-menu li a:hover{background:#367fa9}}.skin-blue-light .main-header .logo{background-color:#3c8dbc;color:#fff;border-bottom:0 solid transparent}.skin-blue-light .main-header .logo:hover{background-color:#3b8ab8}.skin-blue-light .main-header li.user-header{background-color:#3c8dbc}.skin-blue-light .content-header{background:transparent}.skin-blue-light .wrapper,.skin-blue-light .main-sidebar,.skin-blue-light .left-side{background-color:#f9fafc}.skin-blue-light .content-wrapper,.skin-blue-light .main-footer{border-left:1px solid #d2d6de}.skin-blue-light .user-panel>.info,.skin-blue-light .user-panel>.info>a{color:#444}.skin-blue-light .sidebar-menu>li{-webkit-transition:border-left-color .3s ease;-o-transition:border-left-color .3s ease;transition:border-left-color .3s ease}.skin-blue-light .sidebar-menu>li.header{color:#848484;background:#f9fafc}.skin-blue-light .sidebar-menu>li>a{border-left:3px solid transparent;font-weight:600}.skin-blue-light .sidebar-menu>li:hover>a,.skin-blue-light .sidebar-menu>li.active>a{color:#000;background:#f4f4f5}.skin-blue-light .sidebar-menu>li.active{border-left-color:#3c8dbc}.skin-blue-light .sidebar-menu>li.active>a{font-weight:600}.skin-blue-light .sidebar-menu>li>.treeview-menu{background:#f4f4f5}.skin-blue-light .sidebar a{color:#444}.skin-blue-light .sidebar a:hover{text-decoration:none}.skin-blue-light .treeview-menu>li>a{color:#777}.skin-blue-light .treeview-menu>li.active>a,.skin-blue-light .treeview-menu>li>a:hover{color:#000}.skin-blue-light .treeview-menu>li.active>a{font-weight:600}.skin-blue-light .sidebar-form{border-radius:3px;border:1px solid #d2d6de;margin:10px 10px}.skin-blue-light .sidebar-form input[type="text"],.skin-blue-light .sidebar-form .btn{box-shadow:none;background-color:#fff;border:1px solid transparent;height:35px}.skin-blue-light .sidebar-form input[type="text"]{color:#666;border-top-left-radius:2px;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:2px}.skin-blue-light .sidebar-form input[type="text"]:focus,.skin-blue-light .sidebar-form input[type="text"]:focus+.input-group-btn .btn{background-color:#fff;color:#666}.skin-blue-light .sidebar-form input[type="text"]:focus+.input-group-btn .btn{border-left-color:#fff}.skin-blue-light .sidebar-form .btn{color:#999;border-top-left-radius:0;border-top-right-radius:2px;border-bottom-right-radius:2px;border-bottom-left-radius:0}@media (min-width:768px){.skin-blue-light.sidebar-mini.sidebar-collapse .sidebar-menu>li>.treeview-menu{border-left:1px solid #d2d6de}}.skin-blue-light .main-footer{border-top-color:#d2d6de}.skin-blue.layout-top-nav .main-header>.logo{background-color:#3c8dbc;color:#fff;border-bottom:0 solid transparent}.skin-blue.layout-top-nav .main-header>.logo:hover{background-color:#3b8ab8}

View File

@@ -1 +0,0 @@
.skin-green-light .main-header .navbar{background-color:#00a65a}.skin-green-light .main-header .navbar .nav>li>a{color:#fff}.skin-green-light .main-header .navbar .nav>li>a:hover,.skin-green-light .main-header .navbar .nav>li>a:active,.skin-green-light .main-header .navbar .nav>li>a:focus,.skin-green-light .main-header .navbar .nav .open>a,.skin-green-light .main-header .navbar .nav .open>a:hover,.skin-green-light .main-header .navbar .nav .open>a:focus,.skin-green-light .main-header .navbar .nav>.active>a{background:rgba(0,0,0,0.1);color:#f6f6f6}.skin-green-light .main-header .navbar .sidebar-toggle{color:#fff}.skin-green-light .main-header .navbar .sidebar-toggle:hover{color:#f6f6f6;background:rgba(0,0,0,0.1)}.skin-green-light .main-header .navbar .sidebar-toggle{color:#fff}.skin-green-light .main-header .navbar .sidebar-toggle:hover{background-color:#008d4c}@media (max-width:767px){.skin-green-light .main-header .navbar .dropdown-menu li.divider{background-color:rgba(255,255,255,0.1)}.skin-green-light .main-header .navbar .dropdown-menu li a{color:#fff}.skin-green-light .main-header .navbar .dropdown-menu li a:hover{background:#008d4c}}.skin-green-light .main-header .logo{background-color:#00a65a;color:#fff;border-bottom:0 solid transparent}.skin-green-light .main-header .logo:hover{background-color:#00a157}.skin-green-light .main-header li.user-header{background-color:#00a65a}.skin-green-light .content-header{background:transparent}.skin-green-light .wrapper,.skin-green-light .main-sidebar,.skin-green-light .left-side{background-color:#f9fafc}.skin-green-light .content-wrapper,.skin-green-light .main-footer{border-left:1px solid #d2d6de}.skin-green-light .user-panel>.info,.skin-green-light .user-panel>.info>a{color:#444}.skin-green-light .sidebar-menu>li{-webkit-transition:border-left-color .3s ease;-o-transition:border-left-color .3s ease;transition:border-left-color .3s ease}.skin-green-light .sidebar-menu>li.header{color:#848484;background:#f9fafc}.skin-green-light .sidebar-menu>li>a{border-left:3px solid transparent;font-weight:600}.skin-green-light .sidebar-menu>li:hover>a,.skin-green-light .sidebar-menu>li.active>a{color:#000;background:#f4f4f5}.skin-green-light .sidebar-menu>li.active{border-left-color:#00a65a}.skin-green-light .sidebar-menu>li.active>a{font-weight:600}.skin-green-light .sidebar-menu>li>.treeview-menu{background:#f4f4f5}.skin-green-light .sidebar a{color:#444}.skin-green-light .sidebar a:hover{text-decoration:none}.skin-green-light .treeview-menu>li>a{color:#777}.skin-green-light .treeview-menu>li.active>a,.skin-green-light .treeview-menu>li>a:hover{color:#000}.skin-green-light .treeview-menu>li.active>a{font-weight:600}.skin-green-light .sidebar-form{border-radius:3px;border:1px solid #d2d6de;margin:10px 10px}.skin-green-light .sidebar-form input[type="text"],.skin-green-light .sidebar-form .btn{box-shadow:none;background-color:#fff;border:1px solid transparent;height:35px}.skin-green-light .sidebar-form input[type="text"]{color:#666;border-top-left-radius:2px;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:2px}.skin-green-light .sidebar-form input[type="text"]:focus,.skin-green-light .sidebar-form input[type="text"]:focus+.input-group-btn .btn{background-color:#fff;color:#666}.skin-green-light .sidebar-form input[type="text"]:focus+.input-group-btn .btn{border-left-color:#fff}.skin-green-light .sidebar-form .btn{color:#999;border-top-left-radius:0;border-top-right-radius:2px;border-bottom-right-radius:2px;border-bottom-left-radius:0}@media (min-width:768px){.skin-green-light.sidebar-mini.sidebar-collapse .sidebar-menu>li>.treeview-menu{border-left:1px solid #d2d6de}}

View File

@@ -1 +0,0 @@
.skin-purple-light .main-header .navbar{background-color:#605ca8}.skin-purple-light .main-header .navbar .nav>li>a{color:#fff}.skin-purple-light .main-header .navbar .nav>li>a:hover,.skin-purple-light .main-header .navbar .nav>li>a:active,.skin-purple-light .main-header .navbar .nav>li>a:focus,.skin-purple-light .main-header .navbar .nav .open>a,.skin-purple-light .main-header .navbar .nav .open>a:hover,.skin-purple-light .main-header .navbar .nav .open>a:focus,.skin-purple-light .main-header .navbar .nav>.active>a{background:rgba(0,0,0,0.1);color:#f6f6f6}.skin-purple-light .main-header .navbar .sidebar-toggle{color:#fff}.skin-purple-light .main-header .navbar .sidebar-toggle:hover{color:#f6f6f6;background:rgba(0,0,0,0.1)}.skin-purple-light .main-header .navbar .sidebar-toggle{color:#fff}.skin-purple-light .main-header .navbar .sidebar-toggle:hover{background-color:#555299}@media (max-width:767px){.skin-purple-light .main-header .navbar .dropdown-menu li.divider{background-color:rgba(255,255,255,0.1)}.skin-purple-light .main-header .navbar .dropdown-menu li a{color:#fff}.skin-purple-light .main-header .navbar .dropdown-menu li a:hover{background:#555299}}.skin-purple-light .main-header .logo{background-color:#605ca8;color:#fff;border-bottom:0 solid transparent}.skin-purple-light .main-header .logo:hover{background-color:#5d59a6}.skin-purple-light .main-header li.user-header{background-color:#605ca8}.skin-purple-light .content-header{background:transparent}.skin-purple-light .wrapper,.skin-purple-light .main-sidebar,.skin-purple-light .left-side{background-color:#f9fafc}.skin-purple-light .content-wrapper,.skin-purple-light .main-footer{border-left:1px solid #d2d6de}.skin-purple-light .user-panel>.info,.skin-purple-light .user-panel>.info>a{color:#444}.skin-purple-light .sidebar-menu>li{-webkit-transition:border-left-color .3s ease;-o-transition:border-left-color .3s ease;transition:border-left-color .3s ease}.skin-purple-light .sidebar-menu>li.header{color:#848484;background:#f9fafc}.skin-purple-light .sidebar-menu>li>a{border-left:3px solid transparent;font-weight:600}.skin-purple-light .sidebar-menu>li:hover>a,.skin-purple-light .sidebar-menu>li.active>a{color:#000;background:#f4f4f5}.skin-purple-light .sidebar-menu>li.active{border-left-color:#605ca8}.skin-purple-light .sidebar-menu>li.active>a{font-weight:600}.skin-purple-light .sidebar-menu>li>.treeview-menu{background:#f4f4f5}.skin-purple-light .sidebar a{color:#444}.skin-purple-light .sidebar a:hover{text-decoration:none}.skin-purple-light .treeview-menu>li>a{color:#777}.skin-purple-light .treeview-menu>li.active>a,.skin-purple-light .treeview-menu>li>a:hover{color:#000}.skin-purple-light .treeview-menu>li.active>a{font-weight:600}.skin-purple-light .sidebar-form{border-radius:3px;border:1px solid #d2d6de;margin:10px 10px}.skin-purple-light .sidebar-form input[type="text"],.skin-purple-light .sidebar-form .btn{box-shadow:none;background-color:#fff;border:1px solid transparent;height:35px}.skin-purple-light .sidebar-form input[type="text"]{color:#666;border-top-left-radius:2px;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:2px}.skin-purple-light .sidebar-form input[type="text"]:focus,.skin-purple-light .sidebar-form input[type="text"]:focus+.input-group-btn .btn{background-color:#fff;color:#666}.skin-purple-light .sidebar-form input[type="text"]:focus+.input-group-btn .btn{border-left-color:#fff}.skin-purple-light .sidebar-form .btn{color:#999;border-top-left-radius:0;border-top-right-radius:2px;border-bottom-right-radius:2px;border-bottom-left-radius:0}@media (min-width:768px){.skin-purple-light.sidebar-mini.sidebar-collapse .sidebar-menu>li>.treeview-menu{border-left:1px solid #d2d6de}}

View File

@@ -1 +0,0 @@
.skin-red-light .main-header .navbar{background-color:#dd4b39}.skin-red-light .main-header .navbar .nav>li>a{color:#fff}.skin-red-light .main-header .navbar .nav>li>a:hover,.skin-red-light .main-header .navbar .nav>li>a:active,.skin-red-light .main-header .navbar .nav>li>a:focus,.skin-red-light .main-header .navbar .nav .open>a,.skin-red-light .main-header .navbar .nav .open>a:hover,.skin-red-light .main-header .navbar .nav .open>a:focus,.skin-red-light .main-header .navbar .nav>.active>a{background:rgba(0,0,0,0.1);color:#f6f6f6}.skin-red-light .main-header .navbar .sidebar-toggle{color:#fff}.skin-red-light .main-header .navbar .sidebar-toggle:hover{color:#f6f6f6;background:rgba(0,0,0,0.1)}.skin-red-light .main-header .navbar .sidebar-toggle{color:#fff}.skin-red-light .main-header .navbar .sidebar-toggle:hover{background-color:#d73925}@media (max-width:767px){.skin-red-light .main-header .navbar .dropdown-menu li.divider{background-color:rgba(255,255,255,0.1)}.skin-red-light .main-header .navbar .dropdown-menu li a{color:#fff}.skin-red-light .main-header .navbar .dropdown-menu li a:hover{background:#d73925}}.skin-red-light .main-header .logo{background-color:#dd4b39;color:#fff;border-bottom:0 solid transparent}.skin-red-light .main-header .logo:hover{background-color:#dc4735}.skin-red-light .main-header li.user-header{background-color:#dd4b39}.skin-red-light .content-header{background:transparent}.skin-red-light .wrapper,.skin-red-light .main-sidebar,.skin-red-light .left-side{background-color:#f9fafc}.skin-red-light .content-wrapper,.skin-red-light .main-footer{border-left:1px solid #d2d6de}.skin-red-light .user-panel>.info,.skin-red-light .user-panel>.info>a{color:#444}.skin-red-light .sidebar-menu>li{-webkit-transition:border-left-color .3s ease;-o-transition:border-left-color .3s ease;transition:border-left-color .3s ease}.skin-red-light .sidebar-menu>li.header{color:#848484;background:#f9fafc}.skin-red-light .sidebar-menu>li>a{border-left:3px solid transparent;font-weight:600}.skin-red-light .sidebar-menu>li:hover>a,.skin-red-light .sidebar-menu>li.active>a{color:#000;background:#f4f4f5}.skin-red-light .sidebar-menu>li.active{border-left-color:#dd4b39}.skin-red-light .sidebar-menu>li.active>a{font-weight:600}.skin-red-light .sidebar-menu>li>.treeview-menu{background:#f4f4f5}.skin-red-light .sidebar a{color:#444}.skin-red-light .sidebar a:hover{text-decoration:none}.skin-red-light .treeview-menu>li>a{color:#777}.skin-red-light .treeview-menu>li.active>a,.skin-red-light .treeview-menu>li>a:hover{color:#000}.skin-red-light .treeview-menu>li.active>a{font-weight:600}.skin-red-light .sidebar-form{border-radius:3px;border:1px solid #d2d6de;margin:10px 10px}.skin-red-light .sidebar-form input[type="text"],.skin-red-light .sidebar-form .btn{box-shadow:none;background-color:#fff;border:1px solid transparent;height:35px}.skin-red-light .sidebar-form input[type="text"]{color:#666;border-top-left-radius:2px;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:2px}.skin-red-light .sidebar-form input[type="text"]:focus,.skin-red-light .sidebar-form input[type="text"]:focus+.input-group-btn .btn{background-color:#fff;color:#666}.skin-red-light .sidebar-form input[type="text"]:focus+.input-group-btn .btn{border-left-color:#fff}.skin-red-light .sidebar-form .btn{color:#999;border-top-left-radius:0;border-top-right-radius:2px;border-bottom-right-radius:2px;border-bottom-left-radius:0}@media (min-width:768px){.skin-red-light.sidebar-mini.sidebar-collapse .sidebar-menu>li>.treeview-menu{border-left:1px solid #d2d6de}}

View File

@@ -1 +0,0 @@
.skin-yellow-light .main-header .navbar{background-color:#f39c12}.skin-yellow-light .main-header .navbar .nav>li>a{color:#fff}.skin-yellow-light .main-header .navbar .nav>li>a:hover,.skin-yellow-light .main-header .navbar .nav>li>a:active,.skin-yellow-light .main-header .navbar .nav>li>a:focus,.skin-yellow-light .main-header .navbar .nav .open>a,.skin-yellow-light .main-header .navbar .nav .open>a:hover,.skin-yellow-light .main-header .navbar .nav .open>a:focus,.skin-yellow-light .main-header .navbar .nav>.active>a{background:rgba(0,0,0,0.1);color:#f6f6f6}.skin-yellow-light .main-header .navbar .sidebar-toggle{color:#fff}.skin-yellow-light .main-header .navbar .sidebar-toggle:hover{color:#f6f6f6;background:rgba(0,0,0,0.1)}.skin-yellow-light .main-header .navbar .sidebar-toggle{color:#fff}.skin-yellow-light .main-header .navbar .sidebar-toggle:hover{background-color:#e08e0b}@media (max-width:767px){.skin-yellow-light .main-header .navbar .dropdown-menu li.divider{background-color:rgba(255,255,255,0.1)}.skin-yellow-light .main-header .navbar .dropdown-menu li a{color:#fff}.skin-yellow-light .main-header .navbar .dropdown-menu li a:hover{background:#e08e0b}}.skin-yellow-light .main-header .logo{background-color:#f39c12;color:#fff;border-bottom:0 solid transparent}.skin-yellow-light .main-header .logo:hover{background-color:#f39a0d}.skin-yellow-light .main-header li.user-header{background-color:#f39c12}.skin-yellow-light .content-header{background:transparent}.skin-yellow-light .wrapper,.skin-yellow-light .main-sidebar,.skin-yellow-light .left-side{background-color:#f9fafc}.skin-yellow-light .content-wrapper,.skin-yellow-light .main-footer{border-left:1px solid #d2d6de}.skin-yellow-light .user-panel>.info,.skin-yellow-light .user-panel>.info>a{color:#444}.skin-yellow-light .sidebar-menu>li{-webkit-transition:border-left-color .3s ease;-o-transition:border-left-color .3s ease;transition:border-left-color .3s ease}.skin-yellow-light .sidebar-menu>li.header{color:#848484;background:#f9fafc}.skin-yellow-light .sidebar-menu>li>a{border-left:3px solid transparent;font-weight:600}.skin-yellow-light .sidebar-menu>li:hover>a,.skin-yellow-light .sidebar-menu>li.active>a{color:#000;background:#f4f4f5}.skin-yellow-light .sidebar-menu>li.active{border-left-color:#f39c12}.skin-yellow-light .sidebar-menu>li.active>a{font-weight:600}.skin-yellow-light .sidebar-menu>li>.treeview-menu{background:#f4f4f5}.skin-yellow-light .sidebar a{color:#444}.skin-yellow-light .sidebar a:hover{text-decoration:none}.skin-yellow-light .treeview-menu>li>a{color:#777}.skin-yellow-light .treeview-menu>li.active>a,.skin-yellow-light .treeview-menu>li>a:hover{color:#000}.skin-yellow-light .treeview-menu>li.active>a{font-weight:600}.skin-yellow-light .sidebar-form{border-radius:3px;border:1px solid #d2d6de;margin:10px 10px}.skin-yellow-light .sidebar-form input[type="text"],.skin-yellow-light .sidebar-form .btn{box-shadow:none;background-color:#fff;border:1px solid transparent;height:35px}.skin-yellow-light .sidebar-form input[type="text"]{color:#666;border-top-left-radius:2px;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:2px}.skin-yellow-light .sidebar-form input[type="text"]:focus,.skin-yellow-light .sidebar-form input[type="text"]:focus+.input-group-btn .btn{background-color:#fff;color:#666}.skin-yellow-light .sidebar-form input[type="text"]:focus+.input-group-btn .btn{border-left-color:#fff}.skin-yellow-light .sidebar-form .btn{color:#999;border-top-left-radius:0;border-top-right-radius:2px;border-bottom-right-radius:2px;border-bottom-left-radius:0}@media (min-width:768px){.skin-yellow-light.sidebar-mini.sidebar-collapse .sidebar-menu>li>.treeview-menu{border-left:1px solid #d2d6de}}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 656 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 412 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 383 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Some files were not shown because too many files have changed in this diff Show More