Showing preview only (298K chars total). Download the full file or copy to clipboard to get everything.
Repository: tabbyz/chibineko
Branch: master
Commit: 334d18690a05
Files: 206
Total size: 229.6 KB
Directory structure:
gitextract_t1ykuj_k/
├── .gitignore
├── .rspec
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── app/
│ ├── assets/
│ │ ├── images/
│ │ │ └── .keep
│ │ ├── javascripts/
│ │ │ ├── application.coffee
│ │ │ ├── dashboards.coffee
│ │ │ ├── data_table.coffee
│ │ │ ├── move_tests.coffee
│ │ │ ├── projects.coffee
│ │ │ ├── static_pages.coffee
│ │ │ ├── team_users.coffee
│ │ │ ├── teams.coffee
│ │ │ ├── test_preview.coffee
│ │ │ ├── tests.coffee
│ │ │ └── validation.coffee
│ │ └── stylesheets/
│ │ ├── application.scss
│ │ ├── bootstrap_overrides.scss
│ │ ├── color.scss
│ │ ├── common.scss
│ │ ├── data_table.scss
│ │ ├── layouts/
│ │ │ ├── navbar.scss
│ │ │ ├── sidebar.scss
│ │ │ └── style.scss
│ │ ├── static_pages/
│ │ │ ├── terms.scss
│ │ │ └── top.scss
│ │ ├── teams/
│ │ │ └── team_users.scss
│ │ ├── tests/
│ │ │ ├── edit_result_label.scss
│ │ │ ├── form.scss
│ │ │ ├── move.scss
│ │ │ ├── show.scss
│ │ │ └── testcase.scss
│ │ ├── toastr_overrides.scss
│ │ └── vendor/
│ │ ├── best_in_place.scss
│ │ ├── bootgrid.scss
│ │ └── ladda.scss
│ ├── controllers/
│ │ ├── application_controller.rb
│ │ ├── concerns/
│ │ │ └── .keep
│ │ ├── dashboard_controller.rb
│ │ ├── projects_controller.rb
│ │ ├── static_pages_controller.rb
│ │ ├── team_users_controller.rb
│ │ ├── teams_controller.rb
│ │ ├── testcases_controller.rb
│ │ ├── tests_controller.rb
│ │ ├── user_settings_controller.rb
│ │ └── users/
│ │ └── registrations_controller.rb
│ ├── helpers/
│ │ ├── application_helper.rb
│ │ ├── dashboard_helper.rb
│ │ ├── projects_helper.rb
│ │ ├── static_pages_helper.rb
│ │ ├── team_users_helper.rb
│ │ ├── teams_helper.rb
│ │ └── tests_helper.rb
│ ├── mailers/
│ │ └── .keep
│ ├── models/
│ │ ├── .keep
│ │ ├── concerns/
│ │ │ └── .keep
│ │ ├── project.rb
│ │ ├── team.rb
│ │ ├── team_user.rb
│ │ ├── test.rb
│ │ ├── testcase.rb
│ │ └── user.rb
│ └── views/
│ ├── dashboard/
│ │ ├── _navbar.html.slim
│ │ └── index.html.slim
│ ├── devise/
│ │ ├── confirmations/
│ │ │ └── new.html.slim
│ │ ├── mailer/
│ │ │ ├── confirmation_instructions.en.html.slim
│ │ │ ├── confirmation_instructions.ja.html.slim
│ │ │ ├── password_change.html.erb
│ │ │ ├── reset_password_instructions.en.html.slim
│ │ │ └── reset_password_instructions.ja.html.slim
│ │ ├── passwords/
│ │ │ └── new.html.slim
│ │ ├── registrations/
│ │ │ └── new.html.slim
│ │ ├── sessions/
│ │ │ └── new.html.slim
│ │ └── shared/
│ │ └── _links.html.erb
│ ├── layouts/
│ │ ├── _dashboard_sidebar.html.slim
│ │ ├── _logo.html.slim
│ │ ├── _main_menu.html.slim
│ │ ├── _navbar.html.slim
│ │ ├── _root_sidebar.html.slim
│ │ ├── _sign_in_link.html.slim
│ │ ├── _sign_out_link.html.slim
│ │ ├── _sign_up_link.html.slim
│ │ ├── _team_sidebar.html.slim
│ │ └── application.html.slim
│ ├── projects/
│ │ ├── _navbar.html.slim
│ │ ├── _new.html.slim
│ │ ├── _save.js.erb
│ │ ├── _settings.html.slim
│ │ ├── create.js.erb
│ │ ├── new.js.erb
│ │ ├── settings.js.erb
│ │ ├── show.html.slim
│ │ └── update.js.erb
│ ├── static_pages/
│ │ ├── terms.html.slim
│ │ └── top.html.slim
│ ├── team_users/
│ │ ├── _index.html.slim
│ │ ├── _save.js.erb
│ │ ├── create.js.erb
│ │ ├── destroy.js.erb
│ │ └── index.js.erb
│ ├── teams/
│ │ ├── _new.html.slim
│ │ ├── _save.js.erb
│ │ ├── _settings.html.slim
│ │ ├── create.js.erb
│ │ ├── new.js.erb
│ │ ├── settings.js.erb
│ │ ├── show.html.slim
│ │ └── update.js.erb
│ ├── tests/
│ │ ├── _alert.html.slim
│ │ ├── _cheatsheet.en.html.slim
│ │ ├── _cheatsheet.ja.html.slim
│ │ ├── _description.html.slim
│ │ ├── _form.html.slim
│ │ ├── _move.html.slim
│ │ ├── _navbar.html.slim
│ │ ├── _result_label.html.slim
│ │ ├── _table_toolbar.html.slim
│ │ ├── _testcase.html.slim
│ │ ├── bulk_destroy.js.erb
│ │ ├── bulk_move.js.erb
│ │ ├── create.js.erb
│ │ ├── description.js.erb
│ │ ├── edit.html.slim
│ │ ├── move.js.erb
│ │ ├── new.html.slim
│ │ ├── result_label.js.erb
│ │ ├── show.csv.ruby
│ │ ├── show.html.slim
│ │ ├── update.js.erb
│ │ └── update_result_label.js.erb
│ └── user_settings/
│ ├── _modal.html.slim
│ ├── edit.js.erb
│ └── update.js.erb
├── bin/
│ ├── bundle
│ ├── rails
│ ├── rake
│ └── setup
├── circle.yml
├── config/
│ ├── application.rb
│ ├── boot.rb
│ ├── database.yml
│ ├── environment.rb
│ ├── environments/
│ │ ├── development.rb
│ │ ├── production.rb
│ │ └── test.rb
│ ├── i18n-js.yml
│ ├── initializers/
│ │ ├── action_mailer.rb
│ │ ├── assets.rb
│ │ ├── backtrace_silencers.rb
│ │ ├── cookies_serializer.rb
│ │ ├── devise.rb
│ │ ├── filter_parameter_logging.rb
│ │ ├── inflections.rb
│ │ ├── mime_types.rb
│ │ ├── session_store.rb
│ │ ├── time_formats.rb
│ │ └── wrap_parameters.rb
│ ├── locales/
│ │ ├── devise.en.yml
│ │ ├── devise.ja.yml
│ │ ├── devise_view.en.yml
│ │ ├── devise_view.ja.yml
│ │ ├── en.yml
│ │ ├── ja.yml
│ │ ├── js.en.yml
│ │ ├── js.ja.yml
│ │ ├── terms.en.yml
│ │ └── terms.ja.yml
│ ├── mailer.yml.example
│ ├── routes.rb
│ └── secrets.yml
├── config.ru
├── db/
│ ├── migrate/
│ │ ├── 20151224022612_devise_create_users.rb
│ │ ├── 20151224030646_create_teams.rb
│ │ ├── 20151225045046_create_projects.rb
│ │ ├── 20151225141534_create_tests.rb
│ │ ├── 20151226051709_create_testcases.rb
│ │ ├── 20160103121144_add_column_to_user.rb
│ │ ├── 20160109162956_create_team_users.rb
│ │ └── 20160319072222_add_created_at_index_to_test.rb
│ ├── schema.rb
│ └── seeds.rb
├── lib/
│ ├── assets/
│ │ └── .keep
│ └── tasks/
│ └── .keep
├── log/
│ └── .keep
├── public/
│ ├── 404.en.html
│ ├── 404.ja.html
│ ├── 422.en.html
│ ├── 422.ja.html
│ ├── 500.en.html
│ ├── 500.ja.html
│ ├── error.css
│ ├── javascripts/
│ │ └── translations.js
│ ├── maintenance.html
│ └── robots.txt
├── spec/
│ ├── factories/
│ │ ├── testcases.rb
│ │ └── tests.rb
│ ├── models/
│ │ ├── test_spec.rb
│ │ └── testcase_spec.rb
│ ├── rails_helper.rb
│ └── spec_helper.rb
└── vendor/
└── assets/
├── javascripts/
│ ├── .keep
│ └── jquery.readyselector.js
└── stylesheets/
└── .keep
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Ignore bundler config.
/.bundle
/vendor/bundle
# Ignore mailer config.
/config/mailer.yml
# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal
# Ignore all logfiles and tempfiles.
/log/*.log
/tmp
# Ignore other unneeded files.
doc/
*.swp
*~
.project
.DS_Store
.idea
.secret
================================================
FILE: .rspec
================================================
--color
--require spec_helper
================================================
FILE: Gemfile
================================================
source 'https://rubygems.org'
ruby '2.3.0'
gem 'rails', '4.2.4'
gem 'slim-rails', '~> 3.0.0'
gem 'sass-rails', '~> 5.0'
# JavaScript
gem 'i18n-js', '~> 2.1.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.1', '>= 4.1.1'
gem 'therubyracer', platforms: :ruby
gem 'jquery-rails'
gem 'jbuilder', '~> 2.4', '>= 2.4.1'
gem 'gon', '~> 6.0', '>= 6.0.1'
# Other
gem 'bootstrap-sass', '~> 3.3', '>= 3.3.6'
gem 'font-awesome-rails', '~> 4.5', '>= 4.5.0.1'
gem 'bcrypt', '~> 3.1', '>= 3.1.11'
gem 'devise', '~> 3.5', '>= 3.5.6'
gem 'best_in_place', '~> 3.1'
gem 'rails_autolink', '~> 1.1', '>= 1.1.6'
gem 'http_accept_language', '~> 2.0', '>= 2.0.5'
gem 'browser-timezone-rails', github: 'kbaum/browser-timezone-rails'
gem 'turnout', '~> 2.2', '>= 2.2.1'
gem 'actionview-encoded_mail_to', '~> 1.0', '>= 1.0.7'
gem 'momentjs-rails', '~> 2.11'
gem 'kaminari', '~> 0.16.3'
group :development, :test do
gem 'byebug'
gem 'web-console', '~> 3.0'
gem 'spring'
gem 'bullet'
gem 'rspec-rails'
gem 'factory_girl_rails'
gem 'shoulda-matchers'
end
group :development do
gem 'sqlite3'
gem "letter_opener_web"
end
group :production do
gem 'rails_12factor'
gem 'pg'
end
================================================
FILE: LICENSE
================================================
Copyright 2016 SHIFT, Inc. All rights reserved.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2016 SHIFT, Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
# Chibineko
[](https://circleci.com/gh/tabbyz/chibineko)
[](LICENSE)
**Chibineko** is a simple test supporting tool specializing in the management of manual tests.
It is hosted on [https://chibineko.jp](https://chibineko.jp).
## Screenshot
### Top page

### Execute a test

### Create a test

## Quick Start
### Install Chibineko on Heroku
Clone the repo
```console
$ git clone git@github.com:tabbyz/chibineko.git
$ cd chibineko
```
Create a app at Heroku
```console
$ heroku create NAME_FOR_YOUR_APP
```
Push an app to Heroku
```console
$ git push heroku master
```
Initialization of database
```console
$ heroku run rake db:migrate
$ heroku run rake db:seed
```
Set the environment variable
```console
$ heroku config:add SECRET_KEY_BASE=`rake secret`
```
Open your Chibineko and sign in with your credentials
```console
$ heroku open
```
Your username is `test@example.com` and your password is `test` as well.
### Configure Email
You must have email settings to the user registration.
Create a configuration file
```console
$ cp config/mailer.yml.example config/mailer.yml
```
```yaml
# For example, if you want to use Gmail as the SMTP server.
production:
default_url_options:
host: "example.com"
delivery_method: :smtp
smtp_settings:
enable_starttls_auto: true
address: "smtp.gmail.com"
port: 587
domain: "example.com"
authentication: "plain"
user_name: "<yourname>@gmail.com"
password: "<yourpassword>"
```
Remove it from `.gitignore`
```yaml
config/mailer.yml # Remove
```
To commit the changes
```console
$ git add .
$ git commit -m "Configure Email"
```
Push an app to Heroku
```console
$ git push heroku master
```
## Contributing
1. Fork it
1. Create your feature branch (`git checkout -b my-new-feature`)
1. Commit your changes (`git commit -am 'Add some feature'`)
1. Push to the branch (`git push origin my-new-feature`)
1. Create new Pull Request
## License
See [LICENSE](LICENSE).
© SHIFT, Inc. All Rights Reserved.
================================================
FILE: Rakefile
================================================
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require File.expand_path('../config/application', __FILE__)
Rails.application.load_tasks
================================================
FILE: app/assets/images/.keep
================================================
================================================
FILE: app/assets/javascripts/application.coffee
================================================
#= require jquery
#= require jquery_ujs
#= require jquery.cookie
#= require jstz
#= require browser_timezone_rails/set_time_zone
#= require bootstrap-sprockets
#= require best_in_place
#= require Sortable.min
#= require toastr.min
#= require ladda/spin.min
#= require ladda/ladda.min
#= require ladda/ladda.jquery.min
#= require jquery.overlay.min
#= require jquery.bootgrid.min
#= require perfect-scrollbar.jquery.min
#= require moment
#= require moment/ja
#= require jquery.readyselector
#= require i18n
#= require i18n/translations
#= require_tree .
$(document).ready ->
$("[data-toggle='popover']").popover({ container: "body" })
$("[data-toggle='tooltip']").tooltip({ container: "body" })
$(".dropdown-toggle").dropdown()
$(".best_in_place").best_in_place()
$(".carousel").carousel()
$(".hover-scroll").perfectScrollbar()
$(document).on "shown.bs.modal", (e) ->
$("[autofocus]", e.target).focus()
$(document).on "click", ".collapse-btn", (e) ->
if $(this).hasClass("collapsed")
$(this).text(I18n.t("js.common.collapse.expand"))
else
$(this).text(I18n.t("js.common.collapse.close"))
================================================
FILE: app/assets/javascripts/dashboards.coffee
================================================
================================================
FILE: app/assets/javascripts/data_table.coffee
================================================
$(document).ready ->
# Bootgrid settings
$(".data-table").on("initialized.rs.jquery.bootgrid", (e) ->
$(".table-toolbar").hide().appendTo(".actionBar")
).on("loaded.rs.jquery.bootgrid", (e) ->
$(".table-toolbar").hide()
).on("selected.rs.jquery.bootgrid deselected.rs.jquery.bootgrid", (e, rows) ->
count = $(".bootgrid-table tr.active").length
if count == 0
$(".table-toolbar").hide()
else
$(".table-toolbar").show()
$(".table-toolbar .selected-count").text("#{count} #{I18n.t('js.tests.toolbar.selected')}")
).bootgrid
columnSelection: false,
rowCount: -1,
selection: true,
multiSelect: true,
converters: {
date: {
from: (value) -> return moment(value)
to: (value) -> return moment(value).locale(I18n.locale).format("ll")
},
},
formatters: {
title: (column, row) -> return "<a href='/t/#{row.slug.trim()}'>#{row.title}</a>"
},
labels: {
loading: I18n.t("js.bootgrid.loading"),
noResults: I18n.t("js.bootgrid.no_results"),
search: I18n.t("js.bootgrid.search"),
},
templates: {
infos: "",
select: "<input name='select[]' type={{ctx.type}} class='select-box' value={{ctx.value}}>"
}
# Bulk destroy action
$(document).on "click", ".bulk-destroy-btn", ->
if !confirm(I18n.t("js.common.messages.delete_confirm"))
return false
tests = []
for e in $(".bootgrid-table tr.active")
tests.push $(e).data("row-id")
$.ajax
url: "/t/bulk_destroy"
type: 'PATCH'
dataType: 'script'
data: $.param({
tests: tests
})
# Bulk move action
$(document).on "click", ".bulk-move-btn", ->
project = $(this).data("project-id")
tests = []
for e in $(".bootgrid-table tr.active")
tests.push $(e).data("row-id")
$.ajax
url: "/t/bulk_move"
type: 'PATCH'
dataType: 'script'
data: $.param({
tests: tests,
project: project
})
================================================
FILE: app/assets/javascripts/move_tests.coffee
================================================
$(".tests.show").ready ->
$(document).on "click", ".move-test-modal .clickable", ->
$(".project-list .clickable.active").removeClass("active")
$(this).addClass("active")
project_id = $(this).attr("data-project-id")
$(".selected-id-field").val(project_id)
================================================
FILE: app/assets/javascripts/projects.coffee
================================================
================================================
FILE: app/assets/javascripts/static_pages.coffee
================================================
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
================================================
FILE: app/assets/javascripts/team_users.coffee
================================================
$(".projects, .teams, .tests").ready ->
# ==================================================
# Function
# ==================================================
preSearchUser = null
searchUser = (team, email) ->
clearTimeout(preSearchUser)
preSearchUser = setTimeout (->
ajaxSearchUser(team, email)
), 500
ajaxSearchUser = (team, email) ->
btn = $(".ladda-button").ladda()
label = btn.find(".ladda-label")
$.ajax
url: "/teams/#{team}/team_users/ajax_search_user"
type: 'GET'
dataType: 'json'
data: $.param({
email: email
})
beforeSend: (jqXHR, settings) ->
label.text(I18n.t("js.team_sidebar.edit_members.search_user"))
btn.ladda("start")
error: (jqXHR, textStatus, errorThrown) ->
console.log "AJAX Error: #{textStatus}"
btn.ladda("stop")
label.text(I18n.t("js.team_sidebar.edit_members.unknown_error"))
btn.prop("disabled", true)
success: (data, textStatus, jqXHR) ->
if data
label.text(I18n.t("js.team_sidebar.edit_members.add_user"))
btn.ladda("stop")
btn.prop("disabled", false)
else
label.text(I18n.t("js.team_sidebar.edit_members.not_found"))
btn.ladda("stop")
btn.prop("disabled", true)
# ==================================================
# Event
# ==================================================
$(document).on "keyup", "#new_team_user #email", ->
email = $(this).val()
team = $("#team_name").val()
searchUser(team, email)
================================================
FILE: app/assets/javascripts/teams.coffee
================================================
================================================
FILE: app/assets/javascripts/test_preview.coffee
================================================
$(".tests.new, .tests.edit").ready ->
# ==================================================
# Function
# ==================================================
caseTag = (markdown) ->
tag = ""
array = markdown.split(/\r\n|\r|\n/)
for line in array
line = escapeHtml(line)
switch caseType(line)
when "heading"
lv = caseHeadingLevel(line)
body = caseBody(line)
if tag == ""
tag += "<div class='testcase-group'>"
else if lv == 1
tag += "</div><div class='testcase-group'>" if lv == 1
tag += """
<div class="tr heading heading-level-#{lv}">
<div class="td body">
#{body}
</div>
</div>
"""
when "testcase"
tag += "<div class='testcase-group'>" if tag == ""
body = caseBody(line)
tag += """
<div class="tr testcase">
<div class="td number"></div>
<div class="td body">
#{body}
</div>
</div>
"""
tag = "<div class='testcase-list'>" + tag + "</div></div>"
caseHeadingLevel = (text) ->
return -1 if text == ""
text = text.trim()
if text.substr(0, 1) == "#"
text.match(/^#*/)[0].length
else
0
caseType = (text) ->
switch caseHeadingLevel(text)
when -1 then "blank"
when 0 then "testcase"
else "heading"
caseBody = (text) ->
switch caseType(text)
when "heading"
text.match(/^(#*)(.*)/)[2]
when "testcase"
r = text.match(/(.*)(,\s?\[.*\])/)
if r then r[1] else text
preUpdatePreview = null
updatePreview = () ->
clearTimeout(preUpdatePreview)
preUpdatePreview = setTimeout (->
e = $("#test_markdown")
if e.length
if markdown = e.val()
tag = caseTag(markdown)
$(".test-preview-content").empty()
$(".test-preview-content").append(tag)
$(".test-preview-content").show()
$(".test-cheatsheet").hide()
else
$(".test-preview-content").hide()
$(".test-cheatsheet").show()
), 200
escapeHtml = (text) ->
text.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">")
# ==================================================
# Event
# ==================================================
updatePreview()
$(document).on "keyup", "#test_markdown", ->
updatePreview()
# $(document).on "scroll", "#test_markdown", -> # TODO: Doesn't work
$("#test_markdown").scroll ->
syncScroll($(this))
$("#test_markdown").overlay( {
match: /^#.*|\n#.*/g,
css: {"background-color": "#DDD"}
})
# Leave this page
$("#test_markdown").change ->
$(window).on "beforeunload", ->
return I18n.t("js.tests.new.messages.unsaved_changes")
$("input[type=submit]").click ->
$(window).off("beforeunload")
# TODO: To local methods
@syncScroll = (e) ->
source = e
target = $(".test-preview-content")
sourceScrollMax = source.get(0).scrollHeight - source.get(0).offsetHeight
targetScrollMax = target.get(0).scrollHeight - target.get(0).offsetHeight
scrollRatio = source.scrollTop()/ sourceScrollMax
target.scrollTop(targetScrollMax * scrollRatio)
================================================
FILE: app/assets/javascripts/tests.coffee
================================================
$(".tests.show").ready ->
# ==================================================
# Function
# ==================================================
countAll = () ->
$(".result-btn").size()
countLabel = (label) ->
count = 0
for e in $(".result-btn")
count += 1 if $(e).text() == label
count
updateProgressBar = () ->
transition = "width 0.5s ease"
count = countAll()
for text in gon.resultLabelTexts
color = gon.resultLabels[text]
ratio = countLabel(text) / count * 100
$(".progress-animation .progress-bar[data-result-text='#{text}']").css({
width: "#{ratio}%",
WebkitTransition: transition,
MozTransition: transition,
MsTransition: transition,
OTransition: transition,
transition: transition
})
updateProgressCount = () ->
tag = """
<table class='tableX table-condensedX progress-count-list'>
<tbody>
"""
total = countAll()
for text in gon.resultLabelTexts
count = countLabel(text)
ratio = (count / total * 100).toFixed(1)
color = gon.resultLabels[text]
tag += """
<tr>
<td><span class='label color-#{color}'>#{text}</span></td>
<td><strong>#{count}</strong></td>
<td>(#{ratio}%)</td>
</tr>
"""
tag += """
<tr class='count-total'>
<td>#{I18n.t("js.tests.navbar.total")}</td>
<td><strong>#{total}</strong></td>
<td></td>
</tr>
</tbody>
</table>
"""
$(".progress-count").attr("data-content", tag)
removeColorClass = (element) ->
element.removeClass (idx, css) ->
return (css.match(/\bcolor-\S+/g) || []).join(' ')
setResult = (btn, label) ->
dropdownBtn = btn.next()
removeColorClass(btn)
removeColorClass(dropdownBtn)
btn.addClass("color-#{gon.resultLabels[label]}")
dropdownBtn.addClass("color-#{gon.resultLabels[label]}")
btn.text(label)
nextResultLabel = (currentLabel) ->
idx = $.inArray(currentLabel, gon.resultLabelTexts)
if idx == gon.resultLabelTexts.length - 1
gon.resultLabelTexts[0]
else
gon.resultLabelTexts[idx + 1]
prePostResult = null
postResult = (caseId, result) ->
clearTimeout(prePostResult)
prePostResult = setTimeout (->
ajaxPostResult(caseId, result)
), 300
ajaxPostResult = (caseId, result) ->
$.ajax
url: "#{gon.test.slug}/cases/#{caseId}"
type: 'PATCH'
dataType: 'json'
data: $.param({
testcase: { result: result }
})
error: (jqXHR, textStatus, errorThrown) ->
toastr.warning(I18n.t("js.tests.show.errors.conflict"), I18n.t("js.tests.show.errors.please_reload"))
# console.log "Ajax Error: #{textStatus}"
success: (data, textStatus, jqXHR) ->
# console.log "Ajax Successful: #{data}"
# ==================================================
# Event
# ==================================================
updateProgressBar()
updateProgressCount()
# Color picker
$(document).on "click", ".color-picker .color-item", ->
radio = $(this).prev()
color = radio.val()
popover = $(this).parents(".popover")
triggerElement = popover.prev()
removeColorClass(triggerElement)
triggerElement.addClass("color-#{color}")
triggerElement.val(color)
# Use default label
$(document).on "click", ".user-default-result-label", ->
modalBody = $(this).parents(".modal-body")
table = modalBody.find("table")
tableFooter = modalBody.find(".table-footer")
if $(this).is(":checked")
table.hide()
tableFooter.hide()
else
table.show()
tableFooter.show()
# Remove result label
$(document).on "click", ".delete-result-label-icon", ->
# Check item count
tbody = $(this).parents("tbody")
if tbody.find("tr").size() == 1
alert(I18n.t("js.tests.edit_result_label.errors.too_short"))
return
# Remove item
tr = $(this).parents("tr")
tr.remove()
# Add result label
$(document).on "click", ".add-result-label-icon", ->
table = $(this).parent(".table-footer").prev("table")
tbody = table.children("tbody")
tr = tbody.find("tr:first").clone()
# Check item count
if tbody.find("tr").size() == 9
alert(I18n.t("js.tests.edit_result_label.errors.too_long"))
return
# Reset value
textInput = tr.find(".result-label-text > input")
textInput.val("")
colorInput = tr.find(".result-label-color > input")
removeColorClass(colorInput)
colorInput.addClass("color-white")
# Add Item
tbody.append(tr)
$(".select-color").popover({
html : true,
content: $(".popover-content-template").html()
})
$(document).on "click", ".result-btn", ->
label = nextResultLabel($(this).text().trim())
btn = $(this)
setResult(btn, label)
postResult(btn.data("case-id"), label)
updateProgressBar()
updateProgressCount()
$(document).on "click", ".result-item", ->
groupEle = $(this).closest(".result-btn-group")[0]
btn = $(groupEle).children(".result-btn")
label = $(this).text().trim()
setResult(btn, label)
postResult(btn.data("case-id"), label)
updateProgressBar()
updateProgressCount()
$(document).on "blur", ".testcase-list .note input", ->
$(this).parents(".best_in_place").attr("data-original-title", $(this).val())
$(document).on "ajax:error", ".best_in_place", () ->
toastr.warning(I18n.t("js.tests.show.errors.conflict"), I18n.t("js.tests.show.errors.please_reload"))
$(document).on "click", ".js-collapse-btn", ->
heading = $(this).closest(".tr")
headingLv = heading.data("heading-level")
isCollapsed = heading.hasClass("collapsed")
tr = heading.next(".tr")
while tr.length == 1
if tr.hasClass("testcase")
if isCollapsed
tr.show()
else
tr.hide()
tr = tr.next(".tr")
else if tr.hasClass("heading")
if tr.data("heading-level") > headingLv
if isCollapsed
tr.removeClass("collapsed")
else
tr.addClass("collapsed")
tr = tr.next(".tr")
else
break
heading.toggleClass("collapsed")
$(document).on "click", ".js-collapse-all-btn", ->
for heading in $(".heading")
$(heading).addClass("collapsed")
for testcase in $(".testcase")
$(testcase).hide()
$(this).hide()
$(".js-expand-all-btn").show()
$(document).on "click", ".js-expand-all-btn", ->
for heading in $(".heading")
$(heading).removeClass("collapsed")
for testcase in $(".testcase")
$(testcase).show()
$(this).hide()
$(".js-collapse-all-btn").show()
================================================
FILE: app/assets/javascripts/validation.coffee
================================================
$(document).ready ->
$(document).on "keydown", ".form-control.validation", (e) ->
if (e.keyCode != 13)
$(this).popover("destroy")
$(document).on "ajax:beforeSend", "form", (e, xhr, settings) ->
# console.log "ajax:beforeSend"
$(document).on "ajax:success", "form", (e, data, status, xhr) ->
# console.log "ajax:success"
$(document).on "ajax:error", "form", (e, xhr, status, error) ->
# console.log("ajax:error")
errors = $.parseJSON(xhr.responseText)
form = $(e.currentTarget)
name = form.find(".form-control").attr("name")
model = name.match(/^(.*)\[.*\]$/)[1]
for k, v of errors
field = $("##{model}_#{k}")
msg = v
group = field.parent(".form-group")
if group.find(".form-control-feedback").length == 0
group.addClass("has-error has-feedback")
field.popover({ content: msg, placement: "bottom", trigger: "manual" }).popover("show")
popover = group.children(".popover")
popover.addClass("error")
popover.css("left", 0)
group.find(".popover-content").text(msg)
btn = group.nextAll(".ladda-button:first")
btn.ladda().ladda("stop")
$(document).on "ajax:complete", "form", (e, xhr, status) ->
# console.log("complete")
================================================
FILE: app/assets/stylesheets/application.scss
================================================
/*
*= require_tree .
*= require_self
*/
@import "bootstrap-sprockets";
@import "bootstrap";
@import "bootstrap_overrides";
@import "color";
@import "toastr.min";
@import "perfect-scrollbar.min";
@import "toastr_overrides";
@import "ladda-themeless.min";
@import "jquery.bootgrid.min";
@import "font-awesome";
@import "vendor/*";
================================================
FILE: app/assets/stylesheets/bootstrap_overrides.scss
================================================
a {
&:hover, &:focus {
text-decoration: none;
}
}
textarea {
resize: none;
}
.btn, .form-control {
border-radius: 2px;
}
button.btn.ladda-button {
&:focus {
outline: none;
}
}
.btn-link {
&:hover, &:focus {
text-decoration: none;
outline: 0;
}
}
.modal-xs, .modal-sm {
margin: 100px auto;
}
.modal-xs {
width: 300px;
.modal-footer {
padding: 15px;
}
}
.modal-sm {
width: 450px;
}
.modal-dialog {
.modal-content {
border-radius: 0;
.modal-header {
border-bottom: none;
}
.modal-body {
padding: 10px 30px 30px;
}
.modal-footer {
border-top: none;
}
}
}
.dropdown-menu {
.dropdown-header {
padding: 8px 12px 4px 12px;
&:first-child {
padding-top: 4px;
}
}
.divider {
margin: 4px 0;
}
}
// TODO:
.navbar-nav > li {
float: left;
}
.navbar-nav {
margin: 0;
}
.navbar-nav .open .dropdown-menu {
background-color: #FFF;
}
// TODO:
.navbar-right {
float: right !important;
}
================================================
FILE: app/assets/stylesheets/color.scss
================================================
// http://www.materialui.co/colors
// background-color: 400
// background-color(hover): 500
// border-color: 600
.color-red {
background-color: #F44336;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #E53935;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #C62828;
}
}
.color-pink {
background-color: #E91E63;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #D81B60;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #AD1457;
}
}
.color-purple {
background-color: #9C27B0;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #8E24AA;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #6A1B9A;
}
}
.color-deeppurple {
background-color: #673AB7;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #5E35B1;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #4527A0;
}
}
.color-indigo {
background-color: #3F51B5;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #3949AB;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #283593;
}
}
.color-blue {
background-color: #2196F3;
color: #FFF;
outline: 0;
&.btn:hover, &.btn:focus {
background-color: #1E88E5;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #1565C0;
}
}
.color-cyan {
background-color: #00BCD4;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #00ACC1;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #00838F;
}
}
.color-teal {
background-color: #009688;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #00897B;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #00695C;
}
}
.color-green, .color-primary {
background-color: #4CAF50;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #43A047;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #2E7D32;
}
}
.color-lightgreen {
background-color: #8BC34A;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #7CB342;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #558B2F;
}
}
.color-lime {
background-color: #CDDC39;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #C0CA33;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #9E9D24;
}
}
.color-yellow {
background-color: #FFEB3B;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #FDD835;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #F9A825;
}
}
.color-amber {
background-color: #FFC107;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #FFB300;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #FF8F00;
}
}
.color-orange {
background-color: #FF9800;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #FB8C00;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #EF6C00;
}
}
.color-deeporange {
background-color: #FF5722;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #F4511E;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #D84315;
}
}
.color-brown {
background-color: #795548;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #6D4C41;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #4E342E;
}
}
.color-gray {
background-color: #9E9E9E;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #757575;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #616161;
}
}
.color-bluegray {
background-color: #607D8B;
color: #FFF;
&.btn:hover, &.btn:focus {
background-color: #546E7A;
color: #FFF;
}
&.btn, &.label {
border: 1px solid #37474F;
}
}
.color-lightgray {
background-color: #DDD;
color: #424242;
&.btn:hover, &.btn:focus {
background-color: #CCC;
color: #424242;
}
&.btn, &.label {
border: 1px solid #AAA;
}
}
.color-white {
background-color: #FFF;
color: #333;
&.btn:hover, &.btn:focus {
background-color: #EEE;
color: #333;
}
&.btn, &.label {
border: 1px solid #BDBDBD;
}
}
================================================
FILE: app/assets/stylesheets/common.scss
================================================
.modal-fullscreen {
width: 100% !important;
height: 100% !important;
margin: 0 !important;
padding: 20px;
.modal-content {
height: 100%;
border-radius: 0;
.modal-header {
height: 55px;
}
.modal-body {
position: absolute;
top: 55px;
left: 0;
right: 0;
bottom: 50px;
}
.modal-footer {
position: absolute;
bottom: 0;
left: 0;
right: 0;
}
}
}
.text-red {
color: #d32f2f !important;
}
.btn-ghost {
border: 3px solid #FFF;
border-radius: 4px;
background-color: transparent;
color: #FFF;
font-size: 20px;
padding: 18px 20px;
-webkit-transition: all 0.3s ease;
-moz-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
&:hover, &:focus {
background-color: #FFF;
color: #01AB52;
}
}
.inline-block {
display: inline-block !important;
}
.has-feedback .form-control.validation {
padding-right: 16px;
}
.popover.error {
width: 100%;
max-width: 100%;
background-color: #F44336;
color: #FFF;
&.top .arrow:after, &.bottom .arrow:after {
border-bottom-color: #F44336;
}
}
.empty-data {
padding: 140px 0;
text-align: center;
.symbol {
margin-bottom: 10px;
font-size: 150px;
color: #BBB;
}
h3 {
margin-top: 0;
margin-bottom: 40px;
color: #BBB;
font-size: 26px;
}
}
.color-picker {
input[type=radio] {
display: none;
margin: 0;
+ label {
height: 20px;
width: 20px;
padding: 0;
margin: 0;
border-radius: 2px;
cursor: pointer;
}
&:checked + label {
border: 2px solid #333;
}
}
}
.card {
position: relative;
width: 500px;
margin: 0 auto;
padding: 50px 60px;
background-color: #FFF;
border: 1px solid #e8e8e8;
border-radius: .25rem;
box-shadow: 0 1px 0 rgba(0,0,0,.25);
&.card-lg {
width: 800px;
}
&.card-alert {
margin: 20px auto -20px;
padding: 20px;
border-left: 6px solid #C62828;
h2 {
margin-top: 0;
margin-bottom: 16px;
font-size: 16px;
font-weight: bold;
}
ul {
padding-left: 20px;
margin-bottom: 0;
li:not(:last-child) {
margin-bottom: 5px;
}
}
}
&.card-form {
margin: 40px auto 0;
padding: 40px 80px;
text-align: center;
.card-title {
margin-top: 0;
margin-bottom: 30px;
font-size: 28px;
}
.btn[type='submit'] {
margin-bottom: 20px;
}
}
}
.setting-list {
margin-bottom: 0;
padding-left: 0;
list-style: none;
li {
position: relative;
padding-bottom: 20px;
border-bottom: 1px solid #DDD;
&:not(:last-child) {
margin-bottom: 20px;
}
.collapse-btn {
position: absolute;
top: 0;
right: 0;
}
.accordion-title {
font-size: 16px;
font-weight: bold;
}
.accordion-description {
margin-bottom: 20px;
padding-right: 100px;
color: #555;
}
.form-control {
display: inline-block;
margin-right: 5px;
margin-bottom: 5px;
}
}
}
================================================
FILE: app/assets/stylesheets/data_table.scss
================================================
.actionBar .table-toolbar {
display: inline-block;
float: right;
.selected-count {
display: inline-block;
padding: 7px 10px;
margin-right: 10px;
}
.btn {
display: inline-block;
padding: 6px 10px;
}
}
================================================
FILE: app/assets/stylesheets/layouts/navbar.scss
================================================
.navbar {
background-color: #FFF;
> .container-fluid {
margin-top: 7px;
}
.navbar-nav > li > a {
padding: 6px 12px;
border-radius: 2px;
}
.navbar-nav > li:not(:last-child) {
margin-right: 10px;
}
.navbar-nav.pull-right {
padding-right: 20px;
}
}
.navbar.navbar-with-sidebar {
padding-left: 280px;
.navbar-content {
height: 50px;
padding-left: 20px;
padding-right: 20px;
.btn {
padding: 6px 12px;
margin-top: 8px;
}
.navbar-title {
padding: 4px;
display: inline-block;
font-size: 18px;
font-weight: bold;
padding-top: 12px;
.dropdown {
.fa-angle-down {
padding: 0 8px;
font-size: 85%;
}
}
}
}
}
================================================
FILE: app/assets/stylesheets/layouts/sidebar.scss
================================================
.page-with-sidebar {
.sidebar {
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
height: 100%;
}
ul {
list-style: none;
padding-left: 0;
margin: 0;
}
.root-sidebar {
background-color: #192637;
a {
color: #C5D0DE;
display: block;
&:hover, &:focus {
background-color: #364760;
color: #FFF;
}
}
.home-btn, .add-team-btn {
padding: 16px 0;
text-align: center;
}
.home-btn {
background-color: #01AB52;
color: #FFF;
&:hover, &:focus {
background-color: #01AB52;
}
}
.add-team-btn {
background-color: #192637;
font-size: 28px;
}
ul {
-webkit-flex: 1;
flex: 1;
li {
text-align: center;
.team-btn {
height: 60px;
text-align: center;
.hilight-bar {
display: inline-block;
float: left;
width: 4px;
height: 60px;
background-color: transparent;
}
.symbol {
display: block;
font-size: 20px;
font-weight: bold;
padding-top: 6px;
}
.description {
display: inline-block;
overflow: hidden;
width: 46px; // sidebar-width - hilight-bar-width - (margin-left + margin-right)
font-size: 11px;
}
}
}
li.active {
.team-btn {
background-color: #364760;
color: #FFF;
}
.hilight-bar { background-color: #01AB52; }
}
}
}
.team-sidebar {
border-right: 1px solid #DDD;
background-color: #FFF;
.sidebar-title {
.dropdown-toggle {
display: inline-block;
width: 100%;
margin-bottom: 10px;
padding: 10px 20px;
font-size: 20px;
font-weight: bold;
.team-name {
> span {
display: inline-block;
word-wrap: break-word;
max-width: 155px;
}
.fa-angle-down {
padding-top: 0;
width: 20px;
font-size: 85%;
text-align: right;
}
}
&:hover {
background-color: #EEE;
border-radius: 2px;
}
}
.username {
display: block;
overflow: hidden;
margin-top: 5px;
color: #777;
font-size: 14px;
font-weight: normal;
font-style: italic;
}
}
.list-header {
padding: 0 20px;
margin-bottom: 5px;
font-size: 14px;
font-weight: bold;
color: #555;
.add-project-btn {
float: right;
padding: 0 4px;
}
}
.sidebar-list {
-webkit-flex: 1;
flex: 1;
padding: 0 20px;
li {
overflow-x: hidden;
a {
display: inline-block;
width: 100%;
padding: 6px;
font-size: 12px;
font-weight: bold;
}
&:hover, &.active {
background-color: #EEE;
border-radius: 2px;
}
}
}
.coach-mark {
color: #AAA;
font-size: 16px;
height: 60px;
.fa {
margin-top: 22px;
margin-left: 10px;
}
}
}
}
================================================
FILE: app/assets/stylesheets/layouts/style.scss
================================================
body, html {
width: 100%;
height: 100%;
}
body {
-webkit-text-size-adjust: 100%;
margin: 0;
}
body {
&.registrations, &.sessions, &.passwords, &.confirmations, &.static_pages.terms {
padding-top: 50px;
background-color: #F3F3F3;
.navbar {
background-color: #FFF;
box-shadow: 0 1px 1px rgba(0,0,0,.1);
}
.page {
padding: 40px;
}
}
}
.logo {
display: inline-block;
color: #555;
font-size: 24px;
font-weight: bold;
&:hover, &:focus {
color: #555;
}
}
.ps-scrollbar-x-rail, .ps-scrollbar-y-rail {
z-index: 99;
}
.page {
height: 100%;
.contents {
position: relative;
padding: 20px;
min-height: 100%;
}
}
.page-with-sidebar {
.sidebar {
position: fixed;
top: 0;
bottom: 0;
}
.root-sidebar {
left: 0;
width: 60px;
z-index: 40;
}
.team-sidebar {
left: 60px; // Equal to root-sidebar width
width: 220px;
z-index: 30;
}
.contents {
padding-top: 70px;
padding-left: 300px;
z-index: 10;
.navbar {
z-index: 20;
}
}
}
================================================
FILE: app/assets/stylesheets/static_pages/terms.scss
================================================
.terms {
h1 {
margin-top: 0;
}
h2 {
margin-top: 30px;
padding-bottom: 10px;
border-bottom: 1px solid #DDD;
}
}
================================================
FILE: app/assets/stylesheets/static_pages/top.scss
================================================
.static_pages.top {
.navbar {
background-color: #01AB52;
box-shadow: none;
margin-bottom: 0;
border-radius: 0;
.logo {
color: #FFF;
}
.navbar-nav > li > a {
color: #FFF;
&:hover, &:focus {
color: #01AB52;
}
}
}
.contents {
padding: 0;
}
.branding {
background-color: #01AB52;
color: #FFF;
padding: 50px 20px 0;
@media (min-width: 768px) {
padding-top: 100px;
}
h1 {
margin-top: 0;
margin-bottom: 20px;
font-size: 34px;
font-weight: bold;
@media (min-width: 768px) {
font-size: 52px;
}
}
p {
margin-bottom: 70px;
font-size: 18px;
@media (min-width: 768px) {
font-size: 24px;
}
}
.browser-outline {
background-color: #F6F6F6;
max-width: 900px;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
margin-top: 80px;
margin-right: auto;
margin-left: auto;
.browser-header {
text-align: left;
padding: 2px 6px;
font-size: 10px;
@media (min-width: 768px) {
padding: 5px 10px;
font-size: 14px;
}
.browser-btn {
li {
display: inline-block;
margin: 0 2px;
.red { color: #FF4440; }
.yellow { color: #FFBD00; }
.green { color: #00D42A; }
}
}
}
}
.carousel {
border-style: solid;
border-color: #DDD;
border-width: 1px 1px 0 1px;
.carousel-control {
background-image: none;
@media (min-width: 992px) {
&.left { margin-left: -120px; }
&.right { margin-right: -120px; }
}
}
.carousel-indicators {
li {
border-color: #01AB52;
&.active {
background-color: #01AB52;
}
}
}
}
}
.feature {
.col-xs-12 {
margin-bottom: 40px;
}
.feature-item {
.feature-icon {
margin-bottom: 10px;
font-size: 60px;
text-align: center;
}
.feature-title {
margin-bottom: 15px;
font-size: 16px;
font-weight: bold;
text-align: center;
}
.feature-content {
font-size: 14px;
text-align: left;
}
}
}
section {
padding-top: 40px;
padding-bottom: 30px;
text-align: center;
border-top: 1px solid #DDD;
color: #666;
h2 {
margin-bottom: 40px;
font-size: 42px;
font-weight: bold;
}
ul {
display: inline-block;
padding-left: 0;
margin-bottom: 0;
list-style: none;
text-align: left;
li {
margin-bottom: 30px;
font-size: 20px;
.fa {
margin-right: 5px;
}
}
}
}
.footer {
border-top: 1px solid #DDD;
text-align: center;
padding-top: 17px;
padding-bottom: 17px;
position: relative;
a {
color: #555;
&:hover {
text-decoration: underline;
}
}
.list-inline {
display: inline-block;
margin-bottom: 0;
li {
padding-left: 10px;
padding-right: 10px;
}
}
.copyright {
display: block;
margin-top: 18px;
margin-right: 10px;
@media (min-width: 768px) {
position: absolute;
top: 0;
right: 14px;
}
}
}
}
================================================
FILE: app/assets/stylesheets/teams/team_users.scss
================================================
.team-users-modal {
.search-user {
text-align: center;
width: 300px;
margin: 0 auto;
margin-bottom: 30px;
.form-group {
text-align: left;
margin-bottom: 30px;
label {
font-weight: normal;
}
}
.ladda-button {
.fa-chevron-down {
margin-right: 4px;
}
&:disabled .fa-chevron-down {
display: none;
}
}
}
}
================================================
FILE: app/assets/stylesheets/tests/edit_result_label.scss
================================================
.edit-result-label-modal {
.popover-content-template {
display: none;
}
.checkbox {
margin-left: 8px;
}
table {
table-layout: fixed;
width: 100%;
td {
padding: 8px;
}
tr {
.result-label-text {
input {
display: inline-block;
border: none;
outline:none;
padding: 2px 4px;
border-radius: 2px;
width: 100%;
&:hover {
background-color: #FFFFCC;
}
}
}
.result-label-color {
.select-color {
display: inline-block;
width: 20px;
height: 20px;
padding: 0;
color: transparent;
}
}
.drag-handle-icon, .delete-result-label-icon {
color: transparent;
cursor: pointer;
}
.delete-result-label {
text-align: right;
.delete-result-label-icon {
padding: 6px 4px;
}
}
&:hover, &:focus {
.drag-handle-icon {
color: #555;
}
.delete-result-label-icon {
color: #C62828;
}
}
}
}
.table-footer {
display: block;
text-align: right;
padding-right: 2px;
.add-result-label-icon {
cursor: pointer;
width: 30px;
padding: 6px 4px;
text-align: center;
}
}
.drag-handle {
cursor: move !important;
cursor: -webkit-grabbing !important;
}
}
================================================
FILE: app/assets/stylesheets/tests/form.scss
================================================
.tests.new, .tests.edit {
.contents {
position: relative;
.test-title {
position: absolute;
left: 300px;
right: 20px;
top: 55px;
height: 44px;
}
.test-editor {
position: absolute;
top: 110px;
left: 300px;
right: 20px;
bottom: 65px;
border: 1px solid #DDD;
.test-markdown, .test-preview {
display: inline-block;
height: 100%;
width: 50%;
.test-editor-header {
padding: 5px 10px;
height: 30px;
background-color: #EEE;
color: #AAA;
}
}
.test-markdown {
border-right: 1px solid #DDD;
.textoverlay-wrapper {
height: calc(100% - 30px);
}
textarea {
border: none;
width: 100%;
height: 100%;
box-shadow: none;
-moz-box-shadow: none;
-webkit-box-shadow: none;
overflow-x: hidden;
}
}
.test-preview {
float: right;
.test-preview-content, .test-cheatsheet {
width: 100%;
height: calc(100% - 30px);
overflow-y: scroll;
padding: 10px;
}
.test-cheatsheet {
color: #AAA;
padding: 20px;
.cheatsheet-header {
margin-bottom: 15px;
font-size: 18px;
font-weight: bold;
}
.cheatsheet-block {
margin-bottom: 20px;
.cheatsheet-title {
font-size: 14px;
font-weight: bold;
}
.cheatsheet-body {
padding: 10px 15px;
background-color: #FAFAFA;
border-radius: 4px;
line-height: 22px;
}
}
}
}
}
footer {
position: absolute;
left: 20px;
right: 20px;
bottom: 10px;
}
}
}
================================================
FILE: app/assets/stylesheets/tests/move.scss
================================================
.move-test-modal {
.project-list {
.unset-project {
padding: 5px 7px;
font-weight: bold;
}
.team-name {
padding: 2px 10px;
margin-top: 2px;
margin-bottom: 2px;
font-weight: bold;
}
.project-name {
padding: 5px 10px 5px 20px;
}
ul {
&:not(:last-child) {
margin-bottom: 10px;
}
.clickable {
border-radius: 3px;
cursor: pointer;
border: 3px dashed transparent;
&:hover, &:focus {
border-color: #4CAF50;
}
&.active {
background-color: #4CAF50;
color: #C8E6C9;
}
}
}
}
}
================================================
FILE: app/assets/stylesheets/tests/show.scss
================================================
.tests.show {
.progress-count-list {
margin-bottom: 0;
td {
text-align: right;
padding: 4px;
&:first-child {
padding-right: 8px;
}
&:last-child {
color: #777;
}
.label {
display: block;
}
}
tr:nth-last-child(2) > td {
padding-bottom: 10px;
}
tr:last-child {
border-top: 1px solid #AAA;
}
}
.contents {
padding-top: 70px;
.progress.progress-animation {
position: fixed;
left: 0;
right: 0;
bottom: 0;
height: 7px;
padding-top: 1px;
margin-bottom: 0;
z-index: 1030;
border-radius: 0;
box-shadow: none;
background-color: #DDD;
&.margin-sidebar {
padding-left: 280px;
}
}
.test-title {
margin-top: 0;
}
.test-description {
position: relative;
margin-bottom: 20px;
padding: 6px 34px 6px 10px;
background-color: #EEE;
border-radius: 2px;
p {
margin-bottom: 0;
word-wrap: break-word;
}
.placeholder {
color: #BBB;
}
.tool-menu {
position: absolute;
top: 0;
right: 0;
display: inline-block;
}
}
.test-detail {
display: block;
margin-bottom: 30px;
color: #777;
text-align: right;
}
.bip-placeholder {
color: #CCC;
}
}
}
================================================
FILE: app/assets/stylesheets/tests/testcase.scss
================================================
.testcase-list {
.testcase-group {
background-color: #FFF;
border: 1px solid #DDD;
border-top-style: none;
border-radius: 2px;
margin-bottom: 16px;
}
.dropdown-menu {
background-color: #324851;
a { color: #FFF; }
}
.tr {
display: table;
width: 100%;
border-top: 1px solid #DDD;
}
.td {
display: table-cell;
vertical-align: middle;
padding: 2px 2px;
}
.heading {
background-color: #FAFAFA;
color: #717171;
font-size: 14px;
min-height: 29px;
padding: 2px 2px 2px 48px;
word-break: break-all;
.expand-icon, .collapse-icon {
width: 8px;
color: #AAA;
}
.expand-icon {display: none; }
.collapse-icon { display: inline-block; }
&.collapsed {
.expand-icon { display: inline-block; }
.collapse-icon { display: none; }
}
.body {
font-weight: bold;
}
&.heading-level-1 {
font-size: 16px;
letter-spacing: 0.1em;
margin-top: 16px;
padding-left: 8px;
height: 34px;
&:first-child {
margin-top: 0;
}
}
&.heading-level-2 {
padding-left: 18px;
}
&.heading-level-3 {
padding-left: 28px;
}
&.heading-level-4 {
padding-left: 38px;
}
}
.testcase {
height: 43px;
padding-left: 8px;
.number {
color: #CCC;
padding-left: 4px;
width: 30px;
font-size: 12px;
}
.body {
padding: 4px 10px;
line-height: 16px;
}
.result {
.result-btn-group {
.result-btn, .dropdown-toggle {
height: 32px;
}
.result-btn {
width: 110px;
overflow: hidden;
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
font-size: 12px;
}
.dropdown-toggle {
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
}
}
}
.result {
width: 150px;
text-align: center;
.result-item, .result-bulk-item {
display: block;
cursor: pointer;
color: #FFF;
padding: 3px 20px;
margin: 0;
&:hover {
background-color: #E1E3EA;
color: #333;
}
}
}
.note {
width: 200px;
max-width: 200px;
padding: 6px 4px;
.best_in_place {
white-space: nowrap;
overflow: hidden;
}
}
}
================================================
FILE: app/assets/stylesheets/toastr_overrides.scss
================================================
#toast-container > div {
opacity: 1.0;
}
.toast-info {
background-color: #4CAF50;
}
.toast-warning {
background-color: #FF9800;
}
================================================
FILE: app/assets/stylesheets/vendor/best_in_place.scss
================================================
.best_in_place {
display: block;
width: 100%;
padding: 4px;
border: 1px solid transparent;
border-radius: 2px;
&:hover {
background-color: #FFFFCC;
border-color: #CCC;
cursor: text;
}
input, textarea {
width: 100%;
padding: 0;
background-color: transparent;
border: none;
outline: 0;
}
textarea {
resize: none;
margin-bottom: -25px;
white-space: normal;
}
}
================================================
FILE: app/assets/stylesheets/vendor/bootgrid.scss
================================================
.bootgrid-header {
margin-top: 0;
.actionBar {
padding-left: 0;
padding-right: 0;
text-align: left;
.search {
margin-right: 0;
.search-field {
width: 200px;
&:focus {
-webkit-transition: width .15s ease-out .1s;
-moz-transition: width .15s ease-out .1s;
transition: width .15s ease-out .1s;
width: 300px;
}
}
}
}
}
.bootgrid-table {
.no-results {
padding: 30px;
}
}
================================================
FILE: app/assets/stylesheets/vendor/ladda.scss
================================================
.ladda-button {
&:disabled {
cursor: default;
}
&[data-loading=""] .ladda-spinner {
top: 50% !important;
}
.ladda-spinner {
top: 0 !important;
}
}
================================================
FILE: app/controllers/application_controller.rb
================================================
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_filter :set_locale, :set_timezone
class Forbidden < ActionController::ActionControllerError; end
def routing_error
raise ActionController::RoutingError.new("No route matches #{request.path.inspect}")
end
def forbidden_error
redirect_to root_url, flash: { warning: t("errors.forbidden") }
end
def after_sign_in_path_for(resource)
dashboard_path
end
def format_error_message(object)
msgs = object.errors.full_messages
object.errors.messages.each_with_index.map { |(k, v), i| [k, msgs[i]] }.to_h
end
private
def set_locale
client_locale = http_accept_language.compatible_language_from(I18n.available_locales)
if current_user
locale = current_user.locale
if locale.nil?
locale = client_locale
current_user.update(locale: locale)
end
else
locale = client_locale
end
I18n.locale = locale
end
def set_timezone
client_tz = Time.zone.name
if current_user
tz = current_user.timezone
if tz.nil?
tz = client_tz
current_user.update(timezone: tz)
end
else
tz = client_tz
end
Time.zone = tz
end
end
================================================
FILE: app/controllers/concerns/.keep
================================================
================================================
FILE: app/controllers/dashboard_controller.rb
================================================
class DashboardController < ApplicationController
before_action :authenticate_user!
def index
@tests = current_user.tests.includes(:project, project: [:team])
end
end
================================================
FILE: app/controllers/projects_controller.rb
================================================
class ProjectsController < ApplicationController
before_action :authenticate_user!
before_action :authorize!, except: [:new, :create]
def show
@tests = @project.tests.includes(:user)
end
def new
@project = Project.new
end
def edit
end
def create
@project = Project.new(project_params)
@project.user_id = current_user.id
team = Team.find_by(name: params[:team_name])
@project.team_id = team.id
unless @project.save
render json: format_error_message(@project), status: :unprocessable_entity
end
end
def update
unless @project.update(project_params)
render json: format_error_message(@project), status: :unprocessable_entity
end
end
def destroy
@project.destroy
redirect_to team_path(params[:team_name]), notice: t("projects.messages.destroy")
end
def settings
end
private
def set_project
team = Team.find_by(name: params[:team_name])
@project = team.projects.find_by(name: params[:project_name])
routing_error if @project.nil?
end
def authorize!
@project || set_project
forbidden_error unless @project.team.authorized?(current_user)
end
def project_params
params.require(:project).permit(:name, :user_id, :team_id)
end
end
================================================
FILE: app/controllers/static_pages_controller.rb
================================================
class StaticPagesController < ApplicationController
def top
@user = User.new
end
def terms
end
end
================================================
FILE: app/controllers/team_users_controller.rb
================================================
class TeamUsersController < ApplicationController
before_action :authenticate_user!
def index
@team = Team.find_by(name: params[:team_name])
@team_users = @team.team_users.includes(:user)
@team_user = TeamUser.new
end
def create
@team = Team.find_by(name: params[:team_name])
user = User.find_by(email: params[:email])
TeamUser.create(team_id: @team.id, user_id: user.id) unless TeamUser.find_by(team_id: @team.id, user_id: user.id)
@team_users = @team.team_users
@team_user = TeamUser.new
end
def destroy
@team_user = TeamUser.find(params[:id])
@team = @team_user.team
@team_user.destroy
@team_users = @team.team_users
@team_user = TeamUser.new
end
def ajax_search_user
@user = User.find_by(email: params[:email])
render json: @user.present?
end
end
================================================
FILE: app/controllers/teams_controller.rb
================================================
class TeamsController < ApplicationController
before_action :authenticate_user!
before_action :authorize!, except: [:new, :create]
def show
if project = @team.projects.first
redirect_to team_project_path(@team, project)
end
end
def new
@team = current_user.teams.build if user_signed_in?
end
def edit
end
def create
@team = current_user.teams.build(team_params)
@team.user_id = current_user.id
if @team.save
@team.authorized!(current_user)
else
render json: format_error_message(@team), status: :unprocessable_entity
end
end
def update
unless @team.update(team_params)
render json: format_error_message(@team), status: :unprocessable_entity
end
end
def destroy
@team.destroy
redirect_to dashboard_path, notice: t("teams.messages.destroy")
end
def settings
end
private
def set_team
@team = Team.find_by(name: params[:name])
routing_error if @team.nil?
end
def authorize!
@team || set_team
forbidden_error unless @team.authorized?(current_user)
end
def team_params
params.require(:team).permit(:name)
end
end
================================================
FILE: app/controllers/testcases_controller.rb
================================================
class TestcasesController < ApplicationController
before_action :set_testcase, only: [:update]
def update
test = Test.find_by(slug: params[:test_slug])
if @testcase.update(testcase_params)
render json: @testcase, status: 200
else
render json: @testcase.errors, status: :unprocessable_entity, notice: "Unknown error"
end
end
private
def set_testcase
test = Test.find_by(slug: params[:test_slug])
if test.testcases.exists?(id: params[:id])
@testcase = test.testcases.find(params[:id])
else
render json: nil, status: :unprocessable_entity, notice: "Unknown error"
end
end
def testcase_params
params.require(:testcase).permit(:result, :note)
end
end
================================================
FILE: app/controllers/tests_controller.rb
================================================
class TestsController < ApplicationController
before_action :authenticate_user!, except: [:show]
before_action :authorize!, except: [:index, :new, :create, :bulk_move, :bulk_destroy]
def index
@tests = Test.all
end
def show
respond_to do |format|
format.html do
gon.test = @test
gon.resultLabelTexts = @test.result_label_texts
gon.resultLabels = @test.result_labels_or_default
end
format.csv do
encode = "UTF-8"
encode = "Windows-31J" if I18n.locale == :ja
csv_data = render_to_string.encode(encode, :invalid => :replace, :undef => :replace)
send_data csv_data, type: "text/csv; charset=#{encode}", filename: "testcase.csv"
end
end
end
def new
@test = Test.new
# Duplicate test
if source = Test.find_by(slug: params[:source])
@test.project_id = source.project_id
@test.title = source.title
@test.source = source.slug
source.set_markdown(false)
@test.markdown = source.markdown
end
end
def edit
forbidden_error unless @test.user # Owner unknown
@test.set_markdown(true)
end
def create
@test = current_user.tests.build(test_params)
team = Team.find_by(name: params[:test][:team_name])
project = team.projects.find_by(name: params[:test][:project_name]) if team && team.authorized?(current_user)
@test.project_id = project.id if project
# Duplicate test
if source = Test.find_by(slug: @test.source)
@test.description = source.description
@test.result_labels = source.result_labels
end
if @test.save
@test.make_testcase
end
end
def update
@test.updated_at = Time.now
if @test.update(test_params)
@test.make_testcase if @test.markdown
end
end
def destroy
team = view_context.current_team
project = view_context.current_project
@test.destroy
if project
redirect_to team_project_path(team_name: team.name, project_name: project.name), notice: t("tests.messages.destroy")
else
redirect_to dashboard_path, notice: t("tests.messages.destroy")
end
end
def description
end
def result_label
end
def update_result_label
@test.result_labels = nil
if params[:test][:use_default] == "0"
# Use default label
keys = params[:test][:result_label_texts]
vals = params[:test][:result_label_colors]
hash = Hash[*keys.zip(vals).flatten]
@test.result_labels = hash
end
@test.save
end
def move
@teams = current_user.teams
end
def bulk_move
if params[:project].blank?
project_id = nil # Unset project
else
return unless project = Project.find(params[:project]) # Project not found
return unless project.team.authorized?(current_user) # Forbidden error
project_id = project.id # Move to project
end
params[:tests].each do |i|
test = Test.find(i)
next if test.project.nil? && test.user != current_user
next unless test.authorized?(current_user)
test.update_column(:project_id, project_id)
end
end
def bulk_destroy
params[:tests].each do |i|
test = Test.find(i)
next if test.project.nil? && test.user != current_user
next unless test.authorized?(current_user)
test.destroy
end
end
def user_association
@test.update(user_id: current_user.id) unless @test.user
redirect_to @test
end
private
def set_test
@test = Test.find_by(slug: params[:slug])
routing_error if @test.nil?
end
def authorize!
@test || set_test
if @project = @test.project
team = @project.team || Team.find_by(name: params[:team_name])
forbidden_error unless team.authorized?(current_user)
end
end
def test_params
params.require(:test).permit(:title, :description, :project_id, :markdown, :source)
end
end
================================================
FILE: app/controllers/user_settings_controller.rb
================================================
class UserSettingsController < ApplicationController
before_action :authenticate_user!
before_action :set_user, only: [:edit, :update]
def edit
end
def update
unless @user.update(user_params)
render json: format_error_message(@user), status: :unprocessable_entity
end
end
private
def set_user
@user = current_user
end
def user_params
params.require(:user).permit(:username, :timezone, :locale)
end
end
================================================
FILE: app/controllers/users/registrations_controller.rb
================================================
class Users::RegistrationsController < Devise::RegistrationsController
def edit
routing_error # Invalidate a "/users/edit"
end
def update
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)
resource_updated = update_resource(resource, account_update_params)
yield resource if block_given?
if resource_updated
if is_flashing_format?
flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ?
:update_needs_confirmation : :updated
set_flash_message :notice, flash_key
end
sign_in resource_name, resource, bypass: true
# respond_with resource, location: after_update_path_for(resource)
render "user_settings/update"
else
clean_up_passwords resource
# respond_with resource
render json: format_error_message(resource), status: :unprocessable_entity
end
end
end
================================================
FILE: app/helpers/application_helper.rb
================================================
module ApplicationHelper
def controller_action
controller_name + "#" + action_name
end
def color_names
%w(red pink purple deeppurple indigo blue cyan teal green lightgreen lime yellow amber orange deeporange brown gray bluegray lightgray white)
end
def page_title(title)
if title.blank?
"Chibineko: #{I18n.t('.static_pages.top.branding.title')}"
else
"#{title} | Chibineko"
end
end
end
================================================
FILE: app/helpers/dashboard_helper.rb
================================================
module DashboardHelper
end
================================================
FILE: app/helpers/projects_helper.rb
================================================
module ProjectsHelper
def project_collection
current_team.projects if current_team
end
def current_project
team_name = params[:team_name]
project_name = params[:project_name]
if team_name && project_name
team = Team.find_by(name: team_name)
team.projects.find_by(name: project_name)
else
current_test.project if current_test
end
end
end
================================================
FILE: app/helpers/static_pages_helper.rb
================================================
module StaticPagesHelper
end
================================================
FILE: app/helpers/team_users_helper.rb
================================================
module TeamUsersHelper
end
================================================
FILE: app/helpers/teams_helper.rb
================================================
module TeamsHelper
def current_team
if team_name = params[:name] || params[:team_name]
Team.find_by(name: team_name)
elsif current_test
current_test.try(:project).try(:team)
end
end
end
================================================
FILE: app/helpers/tests_helper.rb
================================================
module TestsHelper
def current_test
Test.find_by(slug: params[:slug])
end
end
================================================
FILE: app/mailers/.keep
================================================
================================================
FILE: app/models/.keep
================================================
================================================
FILE: app/models/concerns/.keep
================================================
================================================
FILE: app/models/project.rb
================================================
class Project < ActiveRecord::Base
belongs_to :team
has_many :tests, :dependent => :destroy
before_save { self.name = name.downcase }
validates :name,
presence: true,
uniqueness: { case_sensitive: false, :scope => :team_id },
length: { maximum: 30 },
format: { with: /\A[a-z0-9_]+\z/i }
default_scope { order("id ASC") }
def to_param
name
end
end
================================================
FILE: app/models/team.rb
================================================
class Team < ActiveRecord::Base
has_many :projects, :dependent => :destroy
has_many :team_users, :dependent => :destroy
has_many :users, :through => :team_users
belongs_to :user
before_save { self.name = name.downcase }
validates :name,
presence: true,
uniqueness: { case_sensitive: false },
length: { in: 4..30 },
format: { with: /\A[a-z0-9_]+\z/i }
default_scope { order("id ASC") }
def authorized?(user)
user && self.team_users.find_by(user_id: user.id) ? true : false
end
def authorized!(user)
self.team_users.create(team_id: self.id, user_id: user.id)
end
def to_param
name
end
end
================================================
FILE: app/models/team_user.rb
================================================
class TeamUser < ActiveRecord::Base
belongs_to :team
belongs_to :user
default_scope { order("id ASC") }
end
================================================
FILE: app/models/test.rb
================================================
class Test < ActiveRecord::Base
belongs_to :user
belongs_to :project
has_many :testcases, dependent: :destroy
after_initialize :set_slug
serialize :result_labels
validates :title, presence: true, length: { maximum: 255 }
validates :description, length: { maximum: 4096 }
default_scope { order("id ASC") }
attr_accessor :markdown, :source
def to_param
slug
end
def authorized?(user)
if project = self.project
project.team.authorized?(user)
else
true
end
end
def result_labels_or_default
labels = I18n.t("tests.result_labels")
result_labels || {
labels[:unexecuted] => "white",
labels[:pass] => "green",
labels[:fail] => "red",
labels[:blocked] => "orange",
labels[:na] => "gray",
}
end
def result_label_texts
result_labels_or_default.keys
end
def result_label_colors
result_labels_or_default.values
end
def testcase_groups
groups = []
buff = []
testcases = self.testcases
testcases.each_with_index do |c, i|
buff << c
if testcases[i + 1].try(:heading_level) == 1
groups << buff
buff = []
end
end
groups << buff if buff.size
groups
end
def set_markdown(with_result = false)
array = []
self.testcases.each do |t|
buff = nil
case t.type
when :blank
buff = ""
when :heading
buff = ("#" * t.heading_level) + " " + t.body
when :testcase
buff = t.body
if with_result
if t.result && t.result != self.result_label_texts.first
buff += ", [#{t.result}]"
unless t.note.blank?
buff += ", #{t.note}"
end
end
end
end
array << buff
end
self.markdown = array.join("\n")
end
def make_testcase
self.testcases.delete_all
self.markdown.each_line do |line|
level = Testcase.heading_level(line)
body = Testcase.body(line)
result = Testcase.result(line)
note = Testcase.note(line)
self.testcases.create(heading_level: level, body: body, result: result, note: note)
end
end
private
def set_slug
self.slug = self.slug.blank? ? generate_slug : self.slug
end
def generate_slug
token = SecureRandom.urlsafe_base64
self.class.where(slug: token).blank? ? token : generate_slug
end
end
================================================
FILE: app/models/testcase.rb
================================================
class Testcase < ActiveRecord::Base
belongs_to :test
validates :body, length: { maximum: 1024 }
validates :result, length: { maximum: 255 }
validates :note, length: { maximum: 1024 }
default_scope { order("id ASC") }
def type
case self.heading_level
when -1
:blank
when 0
:testcase
else
:heading
end
end
def result
super || self.test.result_label_texts.first # Default value
end
def result_color
self.test.result_labels_or_default[self.result] || "white" # Default value
end
class << self
def heading_level(text)
return -1 if text.blank?
text.strip!
level = 0
if text.start_with?("#")
text.each_char {|char| char == "#" ? level += 1 : break }
end
level
end
def body(text)
text.try(:strip!)
return nil if text.blank?
level = self.heading_level(text)
if level == 0
text =~ /(.*)(?:,\s\[.*\])/
body = $1 || text
else
body = text[level..-1]
body.strip
end
end
def result(text)
text.try(:strip!)
return nil if text.blank?
text =~ /,(?:\s)?\[(.*)\]/
result = $1
end
def note(text)
text.try(:strip!)
return nil if text.blank?
text =~ /,(?:\s)?\[(?:.*)\],(.*)/
note = $1
note.strip if note
end
end
end
================================================
FILE: app/models/user.rb
================================================
class User < ActiveRecord::Base
has_many :tests
has_many :team_users
has_many :teams, :through => :team_users
validates :email, length: { maximum: 255 }
validates :username, length: { maximum: 30 }
default_scope { order("id ASC") }
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable
def display_name
username || email.split("@").first
end
end
================================================
FILE: app/views/dashboard/_navbar.html.slim
================================================
nav.navbar.navbar-fixed-top.navbar-with-sidebar
.navbar-content
= link_to fa_icon("plus", text: t("common.button.new_test")), new_test_path(team_name: current_team.try(:name), project_name: current_project.try(:name)), class: "btn color-blue new-test-btn pull-right", data: { toggle: "tooltip", placement: "bottom", title: t("common.button.create_new_test") }
================================================
FILE: app/views/dashboard/index.html.slim
================================================
- provide :title, t("dashboard.index.title")
= render "navbar"
- if @tests.size == 0
.empty-data
= fa_icon("inbox", class: "symbol")
h3 = t("projects.show.empty_message")
= link_to fa_icon("plus", text: t(".navbar.new_test")), new_test_path, class: "btn btn-lg color-blue"
- else
= render "tests/table_toolbar"
table.table.table-condensed.table-hover.data-table style="table-layout:fixed;"
thead
tr
th.hidden data-column-id="id" data-type="numeric" data-identifier="true" data-visible="false" ID
th.hidden data-column-id="slug" data-visible="false" slug
th data-column-id="title" data-formatter="title" data-searchable="true" data-width="50%" = t("activerecord.attributes.test.title")
th data-column-id="project" data-searchable="false" = t("common.project")
th data-column-id="updated" data-converter="date" data-searchable="false" data-order="desc" = t("common.updated_on")
tbody
- @tests.reorder("updated_at DESC").each do |test|
tr
td.hidden = test.id
td.hidden = test.slug
td = link_to test.title, test
td = "#{test.project.team.name}##{test.project.name}" if test.project
td = test.updated_at.strftime("%Y-%m-%d %H:%M:%S")
================================================
FILE: app/views/devise/confirmations/new.html.slim
================================================
- if devise_error_messages!.present?
.card.card-alert = devise_error_messages!
.card.card-form
= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f|
h1.card-title = t(".resend_confirmation")
.card-body
.form-group
= f.email_field :email, class: "form-control input-lg", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email), autofocus: true, placeholder: t("activerecord.attributes.user.email"), required: true
= f.submit t(".send_mail"), class: "btn btn-lg color-primary btn-block", data: { disable_with: "Processing" }
================================================
FILE: app/views/devise/mailer/confirmation_instructions.en.html.slim
================================================
p = "Welcome #{@email} !"
p You can confirm your account email through the link below:
p = link_to "Confirm my account", confirmation_url(@resource, confirmation_token: @token)
================================================
FILE: app/views/devise/mailer/confirmation_instructions.ja.html.slim
================================================
p = "ようこそ #{@email} さん。"
p 下記のリンクをクリックして、ユーザ登録を完了してください。
p = link_to "メールアドレスを認証", confirmation_url(@resource, confirmation_token: @token)
================================================
FILE: app/views/devise/mailer/password_change.html.erb
================================================
<p>Hello <%= @resource.email %>!</p>
<p>We're contacting you to notify you that your password has been changed.</p>
================================================
FILE: app/views/devise/mailer/reset_password_instructions.en.html.slim
================================================
p = "Hello #{@resource.email} !"
p Someone has requested a link to change your password. You can do this through the link below.
p = link_to "Change my password", edit_password_url(@resource, reset_password_token: @token)
p If you didn't request this, please ignore this email.
p Your password won't change until you access the link above and create a new one.
================================================
FILE: app/views/devise/mailer/reset_password_instructions.ja.html.slim
================================================
p = "こんにちは #{@resource.email} さん。"
p パスワードリセットのリクエストが行われました。<br>下記のリンクからパスワードを変更することができます。
p = link_to "パスワードを再設定", edit_password_url(@resource, reset_password_token: @token)
p もしこのメールに心当たりがない場合は、無視して下さい。<br>上記リンクをクリックして新しいパスワードを作成しない限り、パスワードは変更されません。
================================================
FILE: app/views/devise/passwords/new.html.slim
================================================
- if devise_error_messages!.present?
.card.card-alert = devise_error_messages!
.card.card-form
= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f|
h1.card-title = t(".forgot_password")
.card-body
.form-group
= f.email_field :email, class: "form-control input-lg", autofocus: true, placeholder: t("activerecord.attributes.user.email"), required: true
= f.submit t(".send_mail"), class: "btn btn-lg btn-block color-primary", data: { disable_with: "Processing" }
================================================
FILE: app/views/devise/registrations/new.html.slim
================================================
- if devise_error_messages!.present?
.card.card-alert = devise_error_messages!
.card.card-form
= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
h1.card-title = t(".sign_up")
.card-body
.form-group
= f.email_field :email, class: "form-control input-lg", autofocus: true, placeholder: t("activerecord.attributes.user.email"), required: true
.form-group
= f.password_field :password, class: "form-control input-lg", autocomplete: "off", placeholder: t("activerecord.attributes.user.password"), required: true
.form-group
= f.password_field :password_confirmation, class: "form-control input-lg", autocomplete: "off", placeholder: t("activerecord.attributes.user.password_confirmation"), required: true
= f.submit t(".sign_up"), class: "btn btn-lg color-primary btn-block", data: { disable_with: "Processing" }
.text-left
= link_to t(".not_receive"), new_confirmation_path(resource_name)
================================================
FILE: app/views/devise/sessions/new.html.slim
================================================
.card.card-form
= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f|
h1.card-title = t(".sign_in")
.card-body
.form-group
= f.email_field :email, class: "form-control input-lg", autofocus: true, placeholder: t("activerecord.attributes.user.email"), required: true
.form-group
= f.password_field :password, class: "form-control input-lg", autocomplete: "off", placeholder: t("activerecord.attributes.user.password"), required: true
= f.submit t(".sign_in"), class: "btn btn-lg color-primary btn-block"
.text-left
= link_to t(".remember_password"), new_password_path(resource_name)
================================================
FILE: app/views/devise/shared/_links.html.erb
================================================
<%- if controller_name != 'sessions' %>
<%= link_to "Log in", new_session_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
<%= link_to "Sign up", new_registration_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
<%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
<%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
<% end -%>
<%- if devise_mapping.omniauthable? %>
<%- resource_class.omniauth_providers.each do |provider| %>
<%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) %><br />
<% end -%>
<% end -%>
================================================
FILE: app/views/layouts/_dashboard_sidebar.html.slim
================================================
.sidebar.team-sidebar
.sidebar-title.dropdown
a.dropdown-toggle aria-expanded="false" aria-haspopup="true" data-toggle="dropdown" href="#" role="button"
.team-name
span = t("dashboard.index.title")
= fa_icon "angle-down"
span.username = current_user.display_name
= render "layouts/main_menu"
ul.sidebar-list
li class="sidebar-list-item active"
= link_to t(".your_test"), dashboard_path
- if current_user.teams.size == 0
.coach-mark = fa_icon("hand-o-left", text: t(".coach_mark"))
================================================
FILE: app/views/layouts/_logo.html.slim
================================================
/ = link_to "Chibineko", root_url, class: "logo"
================================================
FILE: app/views/layouts/_main_menu.html.slim
================================================
ul.dropdown-menu style="top: 44px; left: 18px;"
li.dropdown-header = t("common.you")
li = link_to fa_icon("cog", text: t(".account_settings")), user_settings_edit_path, remote: true
li = render "layouts/sign_out_link"
- if current_team
li.dropdown-header = t("common.team")
li = link_to fa_icon("cog", text: t(".team_settings")), settings_team_path(current_team), remote: true
li = link_to fa_icon("smile-o", text: t(".edit_members")), team_team_users_path(current_team), remote: true
================================================
FILE: app/views/layouts/_navbar.html.slim
================================================
- if controller_action == "static_pages#top"
nav.navbar
.container-fluid
= link_to "Chibineko", root_url, class: "logo"
ul.nav.navbar-nav.navbar-right
li = link_to fa_icon("github-alt", text: t(".github_page")), "https://github.com/tabbyz/chibineko"
- if user_signed_in?
li.dropdown
a href="#" class="dropdown-toggle" data-toggle="dropdown" data-container="body" role="button" aria-expanded="false"
= current_user.display_name
span.caret
ul.dropdown-menu.dropdown-menu-right role="menu"
li = link_to fa_icon("home", text: t("dashboard.index.title")), dashboard_path
li = render "layouts/sign_out_link"
- else
li = render "layouts/sign_in_link"
- else
nav.navbar.navbar-fixed-top
.container-fluid
= link_to "Chibineko", root_url, class: "logo"
ul.nav.navbar-nav.pull-right
- if user_signed_in?
li = render "layouts/sign_out_link"
- else
li = render "layouts/sign_in_link"
li = render "layouts/sign_up_link"
================================================
FILE: app/views/layouts/_root_sidebar.html.slim
================================================
.sidebar.root-sidebar
= link_to fa_icon("home 2x"), dashboard_path, class: "home-btn", data: { toggle: "tooltip", placement: "right", title: t("dashboard.index.title") }
ul.hover-scroll
/ li = link_to fa_icon("home 2x"), dashboard_path, class: "home-btn", data: { toggle: "tooltip", placement: "right", title: t("dashboard.index.title") }
- current_user.teams.reorder("name").each do |team|
li class="#{'active' if team == current_team}"
= link_to team_path(team), class: "team-btn", title: team.name do
.hilight-bar
span.symbol = team.name.first.upcase
span.description = team.name
= link_to fa_icon("plus-circle", right: true), new_team_path, class: "add-team-btn", data: { toggle: "tooltip", placement: "right", title: t(".create_team") }, remote: true
================================================
FILE: app/views/layouts/_sign_in_link.html.slim
================================================
= link_to t("common.button.sign_in"), new_user_session_path
================================================
FILE: app/views/layouts/_sign_out_link.html.slim
================================================
= link_to fa_icon("sign-out", text: t("common.button.sign_out")), destroy_user_session_path, method: :delete
================================================
FILE: app/views/layouts/_sign_up_link.html.slim
================================================
= link_to t("common.button.sign_up"), new_user_registration_path, class: "btn color-blue sign-up"
================================================
FILE: app/views/layouts/_team_sidebar.html.slim
================================================
.sidebar.team-sidebar
.sidebar-title.dropdown
a.dropdown-toggle aria-expanded="false" aria-haspopup="true" data-toggle="dropdown" href="#" role="button"
.team-name
span = current_team.try(:name)
= fa_icon "angle-down"
span.username = current_user.display_name
= render "layouts/main_menu"
.list-header
span = t("common.project")
= link_to fa_icon("plus-circle"), new_team_project_path(current_team), class: "add-project-btn", data: { toggle: "tooltip", placement: "top", title: t("common.button.create_new_project") }, remote: true
ul.sidebar-list.hover-scroll
- current_team.projects.reorder("name").each do |project|
li class="#{'active' if project == current_project}"
= link_to project.name, team_project_path(team_name: current_team.name, project_name: project.name)
================================================
FILE: app/views/layouts/application.html.slim
================================================
doctype html
html
head
title = page_title(yield :title)
- if controller_action == "static_pages#top"
meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"
= stylesheet_link_tag "application", media: "all"
= favicon_link_tag
= include_gon
= javascript_include_tag "application"
= javascript_include_tag "translations"
javascript:
I18n.defaultLocale = "#{I18n.default_locale}"
I18n.locale = "#{I18n.locale}"
I18n.fallbacks = true
= csrf_meta_tags
body class="#{controller_name} #{action_name}"
- if flash
- flash.each do |f|
- type = f[0].to_s.gsub("alert", "warning").gsub("notice", "info")
javascript:
toastr["#{type}"]("#{f[1]}")
- if controller_name.in?(%w"dashboard teams projects tests")
- if user_signed_in?
.page.page-with-sidebar
= render "layouts/root_sidebar"
= current_team ? render("layouts/team_sidebar") : render("layouts/dashboard_sidebar")
.contents == yield
- else
.page
.contents == yield
- else
= render "layouts/navbar"
.page
.contents
== yield
.modal.fade tabindex="-1" role="dialog" aria-hidden="true"
================================================
FILE: app/views/projects/_navbar.html.slim
================================================
nav.navbar.navbar-fixed-top.navbar-with-sidebar
.navbar-content
.navbar-title
.dropdown
a.dropdown-toggle aria-expanded="false" aria-haspopup="true" data-toggle="dropdown" href="#" role="button"
= current_project.try(:name)
= fa_icon "angle-down"
ul.dropdown-menu
li.dropdown-header = t("common.project")
li = link_to fa_icon("cog", text: t(".menu.project_settings")), settings_team_project_path(current_team, current_project), remote: true
= link_to fa_icon("plus", text: t("common.button.new_test")), new_test_path(team_name: current_team.try(:name), project_name: current_project.try(:name)), class: "btn color-blue new-test-btn pull-right", data: { toggle: "tooltip", placement: "bottom", title: t("common.button.create_new_test") }
================================================
FILE: app/views/projects/_new.html.slim
================================================
.new-project-modal.modal-dialog.modal-sm
.modal-content
= form_for @project, url: team_projects_path, remote: true do |f|
.modal-header
button.close type="button" data-dismiss="modal" aria-label="Close"
span aria-hidden="true" ×
h4.modal-title = t(".title")
.modal-body
.form-group
= f.text_field :name, class: "form-control input-lg validation", placeholder: t(".enter_name"), autofocus: true, maxlength: 30, required: true
p.text-danger.error-message
.modal-footer
button.btn.btn-lg.btn-default type="button" data-dismiss="modal" = t("dialog.cancel")
= f.submit class: "btn btn-lg color-primary"
================================================
FILE: app/views/projects/_save.js.erb
================================================
$(".modal").modal("hide")
$(window.location.replace("<%= team_project_path(@project.team.name, @project.name) %>"))
================================================
FILE: app/views/projects/_settings.html.slim
================================================
.project-settings-modal.modal-dialog
.modal-content
.modal-header
button.close type="button" data-dismiss="modal" aria-label="Close"
span aria-hidden="true" ×
h4.modal-title = t(".title")
.modal-body
ul.setting-list
li
= link_to t("common.button.expand"), "#editName", class: "btn color-lightgray collapse-btn", data: { toggle: "collapse" }, aria: { expanded: "false", controls: "editName" }
p.accordion-title = t(".name.title")
p.accordion-description
= t(".name.current_value_html", name: current_project.name)
.collapse#editName
= form_for current_project, url: team_project_path, remote: true do |f|
.form-group.inline-block
= f.text_field :name, class: "form-control validation", style: "width:250px;", maxlength: 255, required: true
= button_tag class: "btn color-green ladda-button", data: { style: "expand-right" } do
= content_tag :span, t("helpers.submit.update"), class: "ladda-label"
li
= link_to t("common.button.expand"), "#deleteProject", class: "btn color-lightgray collapse-btn", data: { toggle: "collapse" }, aria: { expanded: "false", controls: "deleteProject" }
p.accordion-title.text-red = t(".delete.title")
.collapse#deleteProject
p.accordion-description = t(".delete.description")
= link_to t(".delete.delete_project"), team_project_path(current_team.name, current_project.name), class: "btn btn-sm btn-danger", data: { confirm: t("messages.delete_confirm") }, :method => :delete
.modal-footer
button.btn.btn-lg.btn-default type="button" data-dismiss="modal" = t("dialog.close")
================================================
FILE: app/views/projects/create.js.erb
================================================
<%= render 'save' %>
================================================
FILE: app/views/projects/new.js.erb
================================================
$(".modal").html("<%= escape_javascript(render 'new') %>")
$(".modal").modal("show")
================================================
FILE: app/views/projects/settings.js.erb
================================================
$(".modal").html("<%= escape_javascript(render 'settings') %>")
Ladda.bind(".ladda-button")
$(".modal").modal("show")
================================================
FILE: app/views/projects/show.html.slim
================================================
- provide :title, "#{@project.team.name}##{@project.name}"
= render "navbar"
- if @project.tests.size == 0
.empty-data
= fa_icon("inbox", class: "symbol")
h3 = t(".empty_message")
= link_to fa_icon("plus", text: t("common.button.create_new_test")), new_test_path(team_name: current_team.try(:name), project_name: current_project.try(:name)), class: "btn btn-lg color-blue"
- else
= render "tests/table_toolbar"
table.table.table-condensed.table-hover.data-table style="table-layout:fixed;"
thead
tr
th.hidden data-column-id="id" data-type="numeric" data-identifier="true" data-visible="false" ID
th.hidden data-column-id="slug" data-visible="false" slug
th data-column-id="title" data-formatter="title" data-searchable="true" data-width="50%" = t("activerecord.attributes.test.title")
th data-column-id="created" data-searchable="false" = t("common.created_by")
th data-column-id="updated" data-converter="date" data-searchable="false" data-order="desc" = t("common.updated_on")
tbody
- @tests.reorder("updated_at DESC").try(:each) do |test|
tr
td.hidden = test.id
td.hidden = test.slug
td = link_to test.title, test
td = test.user.display_name
td = test.updated_at.strftime("%Y-%m-%d %H:%M:%S")
================================================
FILE: app/views/projects/update.js.erb
================================================
<%= render 'save' %>
================================================
FILE: app/views/static_pages/terms.html.slim
================================================
.card.card-lg
h1.card-title = t(".title")
.card-body
= t(".body_html")
================================================
FILE: app/views/static_pages/top.html.slim
================================================
.container-fluid
.row.branding.text-center
h1 = t(".branding.title")
p = t(".branding.sub_title")
- if user_signed_in?
= link_to t(".branding.get_started"), dashboard_path, class: "btn-ghost"
- else
= link_to t(".branding.sign_up_free"), new_user_registration_path, class: "btn-ghost"
.browser-outline
.browser-header
ul.nav.browser-btn
- %w(red yellow green).each do |color|
li = fa_icon("circle", class: color)
#carousel-screenshot.carousel.slide data-ride="carousel"
ol.carousel-indicators
li.active data-slide-to="0" data-target="#carousel-screenshot"
li data-slide-to="1" data-target="#carousel-screenshot"
li data-slide-to="2" data-target="#carousel-screenshot"
.carousel-inner role="listbox"
- %w(screenshot_1.png screenshot_2.png screenshot_3.png).each_with_index do |file, i|
div class="item #{'active' if i == 1}"
img alt=("First") data-holder-rendered="true" data-src=("First slide") src="images/#{file}" /
a.left.carousel-control data-slide="prev" href="#carousel-screenshot" role="button"
span.glyphicon.glyphicon-chevron-left aria-hidden="true"
span.sr-only Previous
a.right.carousel-control data-slide="next" href="#carousel-screenshot" role="button"
span.glyphicon.glyphicon-chevron-right aria-hidden="true"
span.sr-only Next
section.row.feature
h2 = t(".feature.title")
.container
row
.col-md-3.col-sm-6.col-xs-12.feature-item
.feature-icon = fa_icon("bar-chart")
.feature-title = t(".feature.test_management_title")
.feature-content = t(".feature.test_management_body")
.col-md-3.col-sm-6.col-xs-12.feature-item
.feature-icon = fa_icon("group")
.feature-title = t(".feature.team_management_title")
.feature-content = t(".feature.team_management_body")
.col-md-3.col-sm-6.col-xs-12.feature-item
.feature-icon = fa_icon("share")
.feature-title = t(".feature.share_result_title")
.feature-content = t(".feature.share_result_body")
.col-md-3.col-sm-6.col-xs-12.feature-item
.feature-icon = fa_icon("code-fork")
.feature-title = t(".feature.oss_title")
.feature-content = t(".feature.oss_body")
section.row.section.support
h2 = t(".support")
ul
li = mail_to "support@chibineko.jp", fa_icon("envelope-o", text: "Email"), encode: "hex"
li = link_to fa_icon("github-alt", text: "GitHub Issues"), "https://github.com/tabbyz/chibineko/issues"
li = link_to fa_icon("twitter", text: "Twitter"), "https://twitter.com/chibinekojp"
.row.footer
ul.list-inline
li = link_to t(".terms"), terms_path
li = link_to t(".releases"), "https://github.com/tabbyz/chibineko/releases"
span.copyright
= link_to "© 2015 SHIFT, Inc.", "http://www.shiftinc.jp/", target: "blank"
================================================
FILE: app/views/team_users/_index.html.slim
================================================
.team-users-modal.modal-dialog.modal-sm
.modal-content
.modal-header
button.close type="button" data-dismiss="modal" aria-label="Close"
span aria-hidden="true" ×
h4.modal-title = t(".title")
.modal-body
.search-user
= form_for @team_user, url: team_team_users_path, remote: true do |f|
= hidden_field_tag :team_name, @team.name
.form-group
label = t(".search_user")
= email_field_tag :email, nil, class: "form-control", placeholder: "name@domain.com", required: true
= button_tag type: "submit", class: "btn color-green ladda-button", data: { style: "expand-right" } do
= fa_icon "chevron-down"
= content_tag :span, t(".add_user"), class: "ladda-label"
table.table.table-condensed
thead
tr
th = t("activerecord.attributes.user.email").capitalize
th = t("activerecord.attributes.user.name").capitalize
th
tbody
- @team_users.each do |team_user|
tr
td = team_user.user.email
td = team_user.user.username
td
- if team_user.user != current_user
= form_for team_user, url: team_team_user_path(@team, team_user), :html => { :method => :delete }, remote: true do |form|
= button_tag type: "submit", class: "btn-link", data: { confirm: t(".delete_confirm") } do
= fa_icon "close"
.modal-footer
button.btn.btn-lg.btn-default.pull-right type="button" data-dismiss="modal" = t("dialog.done")
================================================
FILE: app/views/team_users/_save.js.erb
================================================
$(".modal").html("<%= escape_javascript(render 'index') %>")
Ladda.bind(".ladda-button")
================================================
FILE: app/views/team_users/create.js.erb
================================================
<%= render 'save' %>
================================================
FILE: app/views/team_users/destroy.js.erb
================================================
<%= render 'save' %>
================================================
FILE: app/views/team_users/index.js.erb
================================================
$(".modal").html("<%= escape_javascript(render 'index') %>")
Ladda.bind(".ladda-button")
$(".modal").modal("show")
================================================
FILE: app/views/teams/_new.html.slim
================================================
.new-team-modal.modal-dialog.modal-sm
.modal-content
= form_for @team, remote: true do |f|
.modal-header
button.close type="button" data-dismiss="modal" aria-label="Close"
span aria-hidden="true" ×
h4.modal-title = t(".title")
.modal-body
.form-group
= f.text_field :name, class: "form-control input-lg validation", placeholder: t(".enter_name"), autofocus: true, maxlength: 30, required: true
p.text-danger.error-message
.modal-footer
button.btn.btn-lg.btn-default type="button" data-dismiss="modal" = t("dialog.cancel")
= f.submit class: "btn btn-lg color-primary"
================================================
FILE: app/views/teams/_save.js.erb
================================================
$(".modal").modal("hide")
$(window.location.replace("<%= team_path(@team.name) %>"))
================================================
FILE: app/views/teams/_settings.html.slim
================================================
.team-settings-modal.modal-dialog
.modal-content
.modal-header
button.close type="button" data-dismiss="modal" aria-label="Close"
span aria-hidden="true" ×
h4.modal-title = t(".title")
.modal-body
ul.setting-list
li
= link_to t("common.button.expand"), "#editName", class: "btn color-lightgray collapse-btn", data: { toggle: "collapse" }, aria: { expanded: "false", controls: "editName" }
p.accordion-title = t(".name.title")
p.accordion-description
= t(".name.current_value_html", name: current_team.name)
.collapse#editName
= form_for current_team, remote: true do |f|
.form-group.inline-block
= f.text_field :name, class: "form-control validation", style: "width:250px;", maxlength: 255, required: true
= button_tag class: "btn color-green ladda-button", data: { style: "expand-right" } do
= content_tag :span, t("helpers.submit.update"), class: "ladda-label"
li
= link_to t("common.button.expand"), "#deleteTeam", class: "btn color-lightgray collapse-btn", data: { toggle: "collapse" }, aria: { expanded: "false", controls: "deleteTeam" }
p.accordion-title.text-red = t(".delete.title")
.collapse#deleteTeam
p.accordion-description = t(".delete.description")
= link_to t(".delete.delete_team"), current_team, class: "btn btn-sm btn-danger", data: { confirm: t("messages.delete_confirm") }, :method => :delete
.modal-footer
button.btn.btn-lg.btn-default type="button" data-dismiss="modal" = t("dialog.close")
================================================
FILE: app/views/teams/create.js.erb
================================================
<%= render 'save' %>
================================================
FILE: app/views/teams/new.js.erb
================================================
$(".modal").html("<%= escape_javascript(render 'new') %>")
$(".modal").modal("show")
================================================
FILE: app/views/teams/settings.js.erb
================================================
$(".modal").html("<%= escape_javascript(render 'settings') %>")
Ladda.bind(".ladda-button")
$(".modal").modal("show")
================================================
FILE: app/views/teams/show.html.slim
================================================
- provide :title, @team.name
- if @team.projects.size == 0
.empty-data
= fa_icon("inbox", class: "symbol")
h3 = t(".empty_message")
= link_to fa_icon("plus", text: t("common.button.create_new_project")), new_team_project_path(current_team), class: "btn btn-lg color-blue add-project-btn", remote: true
================================================
FILE: app/views/teams/update.js.erb
================================================
<%= render 'save' %>
================================================
FILE: app/views/tests/_alert.html.slim
================================================
- if @test.user && @test.project.nil?
.alert.alert-info
p = t("messages.public_test_html")
- if @test.user.nil?
.alert.alert-warning
p = t("messages.created_by_guest_html")
p
span = t("messages.please_association_html")
= link_to t("messages.attach_current_user"), user_association_test_path, class: "btn btn-sm color-primary", :method => :patch if user_signed_in?
================================================
FILE: app/views/tests/_cheatsheet.en.html.slim
================================================
.cheatsheet
p.cheatsheet-header = fa_icon("question-circle", text: "Tips: how to create test cases")
.cheatsheet-block
p.cheatsheet-title ・Your listed contents can be your test items as it is
p.cheatsheet-body To be able to register an user<br>To be able to sign in
.cheatsheet-block
p.cheatsheet-title ・Group items by adding "#" at the beginning of a line
p.cheatsheet-body # User management function<br>## User registration<br>To be able to register an user<br>## Sign in<br>To be able to log in with correct ID and Password<br>To be unable to log in with wrong ID and Password
================================================
FILE: app/views/tests/_cheatsheet.ja.html.slim
================================================
.cheatsheet
p.cheatsheet-header = fa_icon("question-circle", text: "書き方のヒント")
.cheatsheet-block
p.cheatsheet-title ・箇条書きにした内容がそのままテスト項目になります
p.cheatsheet-body ユーザー登録できること<br>ログインできること
.cheatsheet-block
p.cheatsheet-title ・行の先頭に # を記入するとグループ化することができます
p.cheatsheet-body # ユーザー管理機能<br>## ユーザー登録<br>新規登録できること<br>## ログイン<br>正しいID/PASSでログインできること<br>誤ったID/PASSではエラーが表示されること
================================================
FILE: app/views/tests/_description.html.slim
================================================
.edit-description-modal.modal-dialog.modal-lg
.modal-content
= form_for @test, remote: true do |f|
.modal-header
button.close type="button" data-dismiss="modal" aria-label="Close"
span aria-hidden="true" ×
h4.modal-title = t(".title")
.modal-body
= f.text_area :description, class: "form-control", autofocus: true, rows: 20, maxlength: 4096
.modal-footer
button.btn.btn-lg.btn-default type="button" data-dismiss="modal" = t("dialog.cancel")
= f.submit t("helpers.submit.submit"), class: "btn btn-lg color-primary"
================================================
FILE: app/views/tests/_form.html.slim
================================================
= render "navbar"
= form_for @test, remote: true do |f|
= f.hidden_field :source
= f.hidden_field :team_name, value: current_team.try(:name)
= f.hidden_field :project_name, value: current_project.try(:name)
.test-title
= f.text_field :title, class: "form-control input-lg", placeholder: t(".title_placeholder"), autofocus: (action_name == "new" ? true : false), maxlength: 255, required: true
.test-editor
.test-markdown
.test-editor-header
p = t(".markdown_header")
= f.text_area :markdown, class: "form-control", placeholder: t(".markdown_placeholder"), autofocus: (action_name == "edit" ? true : false), required: true
.test-preview
.test-editor-header
p = t(".preview_header")
.test-preview-content
.test-cheatsheet style="display:none;"
= render "cheatsheet"
footer
= f.submit class: "btn btn-lg color-primary pull-right"
================================================
FILE: app/views/tests/_move.html.slim
================================================
.move-test-modal.modal-dialog.modal-xs
.modal-content
= form_for @test, remote: true do |f|
= f.hidden_field :project_id, class: "selected-id-field"
.modal-header
button.close type="button" data-dismiss="modal" aria-label="Close"
span aria-hidden="true" ×
h4.modal-title = t(".title")
.modal-body
.project-list
ul.nav
li class="unset-project clickable #{'active' if current_project.nil?}" = t(".unset_project")
- @teams.each do |team|
- if team.projects.size != 0
p.team-name = team.name
ul.nav
- team.projects.each do |project|
li data-project-id="#{project.id}" class="project-name clickable #{'active' if project == current_project}"
= project.name
.modal-footer
button.btn.btn-lg.btn-default type="button" data-dismiss="modal" = t("dialog.cancel")
= f.submit t(".submit"), class: "btn btn-lg color-primary"
================================================
FILE: app/views/tests/_navbar.html.slim
================================================
nav.navbar.navbar-fixed-top.navbar-with-sidebar
.navbar-content
- if action_name == "show"
= link_to fa_icon("pencil", text: t(".edit_test")), edit_test_path(@test), class: "btn color-blue edit-test-btn #{'disabled' unless @test.user}", data: { toggle: "tooltip", placement: "bottom", title: t(".edit_current_test") }
- elsif action_name.in?(%w"new edit")
.navbar-title
span = t("tests.form.title.#{action_name}")
ul.nav.navbar-nav.navbar-right
- if action_name == "show"
li = link_to fa_icon("line-chart"), "#", class: "btn progress-count", data: { toggle: "popover", placement: "bottom", trigger: "hover", html: "true", content: "" }
li = link_to fa_icon("download"), test_path(format: :csv), class: "btn", data: { toggle: "tooltip", placement: "bottom", title: t(".export_csv") }
li = link_to fa_icon("copy"), new_test_path(team_name: current_team.try(:name), project_name: current_project.try(:name), source: @test.slug), class: "btn", data: { toggle: "tooltip", placement: "bottom", title: t(".duplicate_test") }
li = link_to fa_icon("file-o"), new_test_path(team_name: current_team.try(:name), project_name: current_project.try(:name)), class: "btn", data: { toggle: "tooltip", placement: "bottom", title: t("common.button.create_new_test") }
- if @test.user
- if @test.project || @test.user == current_user
li.dropdown
a.btn data-target="#" href="#" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"
= fa_icon "cog"
ul.dropdown-menu
li.dropdown-header = t(".test_settings")
li = link_to fa_icon("external-link", text: t(".move_to")), move_test_path(@test), remote: true
li = link_to fa_icon("pencil", text: t(".customize_result_label")), result_label_test_path(@test), remote: true
li.divider role="separator"
li = link_to fa_icon("trash-o", text: t(".delete_test")), @test, class: "text-red", data: { confirm: t("messages.delete_confirm") }, :method => :delete
================================================
FILE: app/views/tests/_result_label.html.slim
================================================
.edit-result-label-modal.modal-dialog.modal-xs
.modal-content
= form_for @test, url: update_result_label_test_path, remote: true do |f|
.modal-header
button.close type="button" data-dismiss="modal" aria-label="Close"
span aria-hidden="true" ×
h4.modal-title = t(".title")
.modal-body
.checkbox
= f.label :use_default do
= f.check_box :use_default, class: "user-default-result-label", checked: (@test.result_labels.nil? ? true : false)
= t(".use_default_label")
table style=("display: none;" if @test.result_labels.nil?)
tbody#resultLabelList
- @test.result_labels_or_default.each do |k, v|
tr
td.drag-handle style="width:30px;"
= fa_icon "bars", class: "drag-handle-icon"
td.result-label-text
= text_field_tag "test[result_label_texts][]", k, { id: nil, placeholder: t(".label_placeholder"), maxlength: 10, required: true }
td.result-label-color style="width:40px;"
input class="btn select-color color-#{v}" name="test[result_label_colors][]" value="#{v}" type="text" tabindex="0" role="button" data-toggle="popover" data-trigger="focus" data-placement="left"
td.delete-result-label style="width:40px;"
= fa_icon("close", class: "delete-result-label-icon")
.over
.table-footer style=("display: none;" if @test.result_labels.nil?)
= fa_icon("plus", class: "add-result-label-icon")
.popover-content-template
.color-picker
- color_names.each do |color|
input type="radio" name="color-radio" id="radio-#{color}" value="#{color}"
label for="radio-#{color}" class="btn color-item color-#{color}"
.modal-footer
button.btn.btn-lg.btn-default type="button" data-dismiss="modal" = t("dialog.cancel")
= f.submit t("helpers.submit.submit"), class: "btn btn-lg color-primary"
================================================
FILE: app/views/tests/_table_toolbar.html.slim
================================================
.table-toolbar
span.selected-count
ul.nav.navbar-nav.navbar-right
li = link_to fa_icon("trash-o", text: t("common.button.delete")), "#", class: "btn text-red bulk-destroy-btn"
li.dropdown
a.btn data-target="#" href="#" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"
= fa_icon "external-link", text: t("common.button.move")
ul.dropdown-menu
li = link_to t("tests.move.unset_project"), "#", class: "bulk-move-btn"
- current_user.teams.includes(:projects).each do |team|
li.dropdown-header = team.name
- team.projects.each do |project|
li = link_to project.name, "#", class: "bulk-move-btn", data: { project_id: project.id }
================================================
FILE: app/views/tests/_testcase.html.slim
================================================
.testcase-toolbar
button type="button" class="btn-link js-collapse-all-btn"
= fa_icon "caret-down", text: t(".collapse_all"), class: "collapse-icon"
button type="button" class="btn-link js-expand-all-btn" style="display:none;"
= fa_icon "caret-right", text: t(".expand_all"), class: "expand-icon"
.testcase-list
- case_id = 0
- @test.testcase_groups.each do |group|
.testcase-group
- group.each do |c|
- case c.type
- when :heading
div class="tr heading heading-level-#{c.heading_level}" data-heading-level="#{c.heading_level}"
.td.body
= fa_icon "caret-down", class: "collapse-icon"
= fa_icon "caret-right", class: "expand-icon"
button type="button" class="btn-link js-collapse-btn" = c.body
- when :testcase
.tr.testcase
.td.number = case_id += 1
.td.body = c.body
.td.result
.btn-group.result-btn-group
= button_tag c.result, type: "button", class: "btn result-btn color-#{c.result_color}", data: { "case-id" => c.id }
= button_tag type: "button", class: "btn dropdown-toggle color-#{c.result_color}", data: { toggle: "dropdown" } do
span.caret
span.sr-only Toggle Dropdown
ul.dropdown-menu.pull-right role="menu"
- @test.result_label_texts.each do |label|
li
p.result-item = label
.td.note = best_in_place c, :note, url: test_testcase_path(test_slug: @test.slug, id: c.id), place_holder: t(".note"), html_attrs: { maxlength: 1024 }, data: { toggle: "tooltip", placement: "top", "original-title" => c.note }
================================================
FILE: app/views/tests/bulk_destroy.js.erb
================================================
window.location.reload()
================================================
FILE: app/views/tests/bulk_move.js.erb
================================================
window.location.reload()
================================================
FILE: app/views/tests/create.js.erb
================================================
$(".modal").modal("hide")
$(window.location.replace("<%= test_path(@test.slug) %>"))
================================================
FILE: app/views/tests/description.js.erb
================================================
$(".modal").html("<%= escape_javascript(render 'description') %>")
$(".modal").modal("show")
================================================
FILE: app/views/tests/edit.html.slim
================================================
= render "form"
================================================
FILE: app/views/tests/move.js.erb
================================================
$(".modal").html("<%= escape_javascript(render 'move') %>")
$(".modal").modal("show")
================================================
FILE: app/views/tests/new.html.slim
================================================
= render "form"
================================================
FILE: app/views/tests/result_label.js.erb
================================================
$(".modal").html("<%= escape_javascript(render 'result_label') %>")
$(".modal").modal("show")
Sortable.create(resultLabelList, { handle: ".drag-handle" });
$(".select-color").popover({
html : true,
content: $(".popover-content-template").html()
})
================================================
FILE: app/views/tests/show.csv.ruby
================================================
require 'csv'
testcases = @test.testcases
# Examine the maximum heading level
max_level = 0
testcases.each do |c|
if c.type == :heading
max_level = c.heading_level if c.heading_level > max_level
end
end
headings = Array.new(max_level)
# Header
header = Array.new(max_level, "-")
header << I18n.t("tests.csv.case") << I18n.t("tests.csv.result") << I18n.t("tests.csv.note")
# Generate csv
CSV.generate(headers: header, write_headers: true, force_quotes: true) do |csv|
# CSV.generate do |csv|
testcases.each do |c|
case c.type
when :heading
# Clear unnecessary column
length = max_level - c.heading_level
headings[c.heading_level, length] = Array.new(length, "")
# Set value to column
headings[c.heading_level - 1] = c.body
when :testcase
row = Array.new(headings)
row << c.body << c.result << c.note
csv << row
end
end
end
================================================
FILE: app/views/tests/show.html.slim
================================================
- provide :title, @test.title
- if !user_signed_in?
= render "layouts/navbar"
- else
= render "navbar"
.progress.progress-animation class=(user_signed_in? ? "margin-sidebar" : "")
- @test.result_labels_or_default.drop(1).push(@test.result_labels_or_default.first).each do |k, v|
div class="progress-bar progress-bar-xs color-#{v}" style="width: 0%; transition: width 0.5s ease;" data-result-text="#{k}"
= render "alert"
h3.test-title = @test.title
.test-description
- if @test.description.blank?
p.placeholder = t(".blank_description")
- else
= auto_link simple_format(html_escape(@test.description)), :html => { target: "_blank" }
.tool-menu
= link_to fa_icon("pencil"), description_test_path(@test), class: "btn", data: { toggle: "tooltip", placement: "left", title: t("tests.description.title") }, remote: true if @test.user && user_signed_in?
.test-detail
span = t(".created_by", username: @test.user ? @test.user.display_name : t("common.guest"), updated_at: l(@test.updated_at, format: :short))
= render "testcase"
================================================
FILE: app/views/tests/update.js.erb
================================================
$(".modal").modal("hide")
$(window.location.replace("<%= test_path(@test.slug) %>"))
================================================
FILE: app/views/tests/update_result_label.js.erb
================================================
$(".modal").modal("hide")
$(window.location.reload())
================================================
FILE: app/views/user_settings/_modal.html.slim
================================================
.account-settings-modal.modal-dialog
.modal-content
.modal-header
button.close type="button" data-dismiss="modal" aria-label="Close"
span aria-hidden="true" ×
h4.modal-title = t(".title")
.modal-body
ul.setting-list
li
= link_to t("common.button.expand"), "#editUsername", class: "btn color-lightgray collapse-btn", data: { toggle: "collapse" }, aria: { expanded: "false", controls: "editUsername" }
p.accordion-title = t(".username.title")
p.accordion-description
- if @user.username.blank?
= t(".username.blank")
- else
= t(".username.current_value_html", username: @user.username)
.collapse#editUsername
= form_for @user, url: user_settings_update_path, remote: true do |f|
.form-group.inline-block
= f.text_field :username, class: "form-control validation", style: "width:200px;", maxlength: 255, required: true
= button_tag class: "btn color-green ladda-button", data: { style: "expand-right" } do
= content_tag :span, t("helpers.submit.submit"), class: "ladda-label"
li
= link_to t("common.button.expand"), "#editPassword", class: "btn color-lightgray collapse-btn", data: { toggle: "collapse" }, aria: { expanded: "false", controls: "editPassword" }
p.accordion-title = t(".password.title")
p.accordion-description = t(".password.change_password")
.collapse#editPassword
= form_for @user, as: "user", url: registration_path("user"), html: { method: :put }, remote: true do |f|
.form-group.inline-block
label for="user_current_password" = t(".password.current_password")
= f.password_field :current_password, class: "form-control validation", style: "width:200px; display:block;", required: true
br
.form-group.inline-block
label for="user_password" = t(".password.new_password")
= f.password_field :password, class: "form-control validation", style: "width:200px; display:block;", autocomplete: "off", required: true
br
.form-group.inline-block
label for="user_password" = t(".password.confirm_password")
= f.password_field :password_confirmation, class: "form-control validation", style: "width:200px; display:block;", autocomplete: "off", required: true
br
= button_tag class: "btn color-green ladda-button", data: { style: "expand-right" } do
= content_tag :span, t(".password.update"), class: "ladda-label"
li
= link_to t("common.button.expand"), "#editTimezone", class: "btn color-lightgray collapse-btn", data: { toggle: "collapse" }, aria: { expanded: "false", controls: "editTimezone" }
p.accordion-title = t(".timezone.title")
p.accordion-description
= t(".timezone.current_value_html", timezone: @user.timezone)
.collapse#editTimezone
= form_for @user, url: user_settings_update_path, remote: true do |f|
= f.time_zone_select :timezone, nil, { include_blank: false }, { class: "form-control", required: true }
= button_tag class: "btn color-green ladda-button", data: { style: "expand-right" } do
= content_tag :span, t(".timezone.update"), class: "ladda-label"
li
= link_to t("common.button.expand"), "#editLanguage", class: "btn color-lightgray collapse-btn", data: { toggle: "collapse" }, aria: { expanded: "false", controls: "editLanguage" }
p.accordion-title = t(".language.title")
p.accordion-description
= t(".language.current_value_html", language: t("language_name"))
.collapse#editLanguage
= form_for @user, url: user_settings_update_path, remote: true do |f|
= f.select :locale, { "English" => "en", "日本語" => "ja" }, {}, { class: "form-control", style: "width:200px;" }
= button_tag class: "btn color-green ladda-button", data: { style: "expand-right" } do
= content_tag :span, t("helpers.submit.submit"), class: "ladda-label"
.modal-footer
button.btn.btn-lg.btn-default type="button" data-dismiss="modal" = t("dialog.close")
================================================
FILE: app/views/user_settings/edit.js.erb
================================================
$(".modal").html("<%= escape_javascript(render 'modal') %>")
Ladda.bind(".ladda-button")
$(".modal").modal("show")
================================================
FILE: app/views/user_settings/update.js.erb
================================================
$(".modal").modal("hide")
$(window.location.reload())
================================================
FILE: bin/bundle
================================================
#!/usr/bin/env ruby
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
load Gem.bin_path('bundler', 'bundle')
================================================
FILE: bin/rails
================================================
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'
================================================
FILE: bin/rake
================================================
#!/usr/bin/env ruby
require_relative '../config/boot'
require 'rake'
Rake.application.run
================================================
FILE: bin/setup
================================================
#!/usr/bin/env ruby
require 'pathname'
# path to your application root.
APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
Dir.chdir APP_ROOT do
# This script is a starting point to setup your application.
# Add necessary setup steps to this file:
puts "== Installing dependencies =="
system "gem install bundler --conservative"
system "bundle check || bundle install"
# puts "\n== Copying sample files =="
# unless File.exist?("config/database.yml")
# system "cp config/database.yml.sample config/database.yml"
# end
puts "\n== Preparing database =="
system "bin/rake db:setup"
puts "\n== Removing old logs and tempfiles =="
system "rm -f log/*"
system "rm -rf tmp/cache"
puts "\n== Restarting application server =="
system "touch tmp/restart.txt"
end
================================================
FILE: circle.yml
================================================
machine:
ruby:
version: 2.3.0
database:
pre:
- cp config/mailer.yml.example config/mailer.yml
================================================
FILE: config/application.rb
================================================
require File.expand_path('../boot', __FILE__)
require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "sprockets/railtie"
# require "rails/test_unit/railtie"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module Chibineko
class Application < Rails::Application
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
# config.time_zone = 'Central Time (US & Canada)'
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
# config.i18n.default_locale = :de
config.i18n.available_locales = %w(en ja)
# Do not swallow errors in after_commit/after_rollback callbacks.
config.active_record.raise_in_transactional_callbacks = true
config.assets.initialize_on_precompile = true
config.web_console.development_only = false
end
end
================================================
FILE: config/boot.rb
================================================
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' # Set up gems listed in the Gemfile.
================================================
FILE: config/database.yml
================================================
# SQLite version 3.x
# gem install sqlite3
#
# Ensure the SQLite 3 gem is defined in your Gemfile
# gem 'sqlite3'
#
default: &default
adapter: sqlite3
pool: 5
timeout: 5000
development:
<<: *default
database: db/development.sqlite3
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: db/test.sqlite3
production:
<<: *default
database: db/production.sqlite3
================================================
FILE: config/environment.rb
================================================
# Load the Rails application.
require File.expand_path('../application', __FILE__)
# Initialize the Rails application.
Rails.application.initialize!
================================================
FILE: config/environments/development.rb
================================================
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Do not eager load code on boot.
config.eager_load = false
# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false
# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log
# Raise an error on page load if there are pending migrations.
config.active_record.migration_error = :page_load
# Debug mode disables concatenation and preprocessing of assets.
# This option may cause significant delays in view rendering with a large
# number of complex assets.
config.assets.debug = true
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
# yet still be able to expire them through the digest params.
config.assets.digest = true
# Adds additional error checking when serving assets at runtime.
# Checks for improperly declared sprockets dependencies.
# Raises helpful error messages.
config.assets.raise_runtime_errors = true
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
# Bullet settings
config.after_initialize do
Bullet.enable = true
Bullet.alert = true
Bullet.console = true
Bullet.rails_logger = true
end
# Mailer settings.
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :letter_opener_web
end
================================================
FILE: config/environments/production.rb
================================================
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# Code is not reloaded between requests.
config.cache_classes = true
# Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
config.eager_load = true
# Full error reports are disabled and caching is turned on.
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Enable Rack::Cache to put a simple HTTP cache in front of your application
# Add `rack-cache` to your Gemfile before enabling this.
# For large-scale production use, consider using a caching reverse proxy like
# NGINX, varnish or squid.
# config.action_dispatch.rack_cache = true
# Compress JavaScripts and CSS.
config.assets.js_compressor = :uglifier
# config.assets.css_compressor = :sass
# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
# yet still be able to expire them through the digest params.
config.assets.digest = true
# Disable Rails's static asset server (Apache or nginx will already do this).
config.serve_static_files = true
# `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
# Specifies the header that your server uses for sending files.
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
config.force_ssl = true
# Use the lowest log level to ensure availability of diagnostic information
# when problems arise.
config.log_level = :debug
# Prepend all log lines with the following tags.
# config.log_tags = [ :subdomain, :uuid ]
# Use a different logger for distributed setups.
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
# Use a different cache store in production.
# config.cache_store = :mem_cache_store
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = 'http://assets.example.com'
# Ignore bad email addresses and do not raise email delivery errors.
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
# config.action_mailer.raise_delivery_errors = false
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners.
config.active_support.deprecation = :notify
# Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
end
================================================
FILE: config/environments/test.rb
================================================
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
# The test environment is used exclusively to run your application's
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
config.cache_classes = true
# Do not eager load code on boot. This avoids loading your whole application
# just for the purpose of running a single test. If you are using a tool that
# preloads Rails for running tests, you may have to set it to true.
config.eager_load = false
# Configure static file server for tests with Cache-Control for performance.
config.serve_static_files = true
config.static_cache_control = 'public, max-age=3600'
# Show full error reports and disable caching.
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Raise exceptions instead of rendering exception templates.
config.action_dispatch.show_exceptions = false
# Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false
# Tell Action Mailer not to deliver emails to the real world.
# The :test delivery method accumulates sent emails in the
# ActionMailer::Base.deliveries array.
config.action_mailer.delivery_method = :test
# Randomize the order test cases are executed.
config.active_support.test_order = :random
# Print deprecation notices to the stderr.
config.active_support.deprecation = :stderr
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
end
================================================
FILE: config/i18n-js.yml
================================================
# Split context in several files.
# By default only one file with all translations is exported and
# no configuration is required. Your settings for asset pipeline
# are automatically recognized.
#
# If you want to split translations into several files or specify
# locale contexts that will be exported, just use this file to do
# so.
#
# If you're going to use the Rails 3.1 asset pipeline, change
# the following configuration to something like this:
#
# translations:
# - file: "app/assets/javascripts/i18n/translations.js"
#
# If you're running an old version, you can use something
# like this:
#
translations:
- file: "public/javascripts/translations.js"
only: "*.js"
================================================
FILE: config/initializers/action_mailer.rb
================================================
unless Chibineko::Application.config.action_mailer.nil?
if options = YAML.load_file(Rails.root.join("config", "mailer.yml"))[Rails.env]
Chibineko::Application.config.action_mailer.merge! options.deep_symbolize_keys!
end
end
================================================
FILE: config/initializers/assets.rb
================================================
# Be sure to restart your server when you modify this file.
# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = '1.0'
# Add additional assets to the asset load path
# Rails.application.config.assets.paths << Emoji.images_path
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
# Rails.application.config.assets.precompile += %w( search.js )
================================================
FILE: config/initializers/backtrace_silencers.rb
================================================
# Be sure to restart your server when you modify this file.
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
# Rails.backtrace_cleaner.remove_silencers!
================================================
FILE: config/initializers/cookies_serializer.rb
================================================
# Be sure to restart your server when you modify this file.
Rails.application.config.action_dispatch.cookies_serializer = :json
================================================
FILE: config/initializers/devise.rb
================================================
# Use this hook to configure devise mailer, warden hooks and so forth.
# Many of these configuration options can be set straight in your model.
Devise.setup do |config|
# The secret key used by Devise. Devise uses this key to generate
# random tokens. Changing this key will render invalid all existing
# confirmation, reset password and unlock tokens in the database.
# Devise will use the `secret_key_base` on Rails 4+ applications as its `secret_key`
# by default. You can change it below and use your own secret key.
# config.secret_key = '35175ed82fda77f2e1c26412bc6ae3d0c295fdfc00205063ab570e74ffc1b1a6217959602c468032b3fecbb119f517d9a3c144f9a43892585470c3c5f1a1fc5e'
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class
# with default "from" parameter.
config.mailer_sender = '"Chibineko" <noreply@chibineko.jp>'
# Configure the class responsible to send e-mails.
# config.mailer = 'Devise::Mailer'
# ==> ORM configuration
# Load and configure the ORM. Supports :active_record (default) and
# :mongoid (bson_ext recommended) by default. Other ORMs may be
# available as additional gems.
require 'devise/orm/active_record'
# ==> Configuration for any authentication mechanism
# Configure which keys are used when authenticating a user. The default is
# just :email. You can configure it to use [:username, :subdomain], so for
# authenticating a user, both parameters are required. Remember that those
# parameters are used only when authenticating and not when retrieving from
# session. If you need permissions, you should implement that in a before filter.
# You can also supply a hash where the value is a boolean determining whether
# or not authentication should be aborted when the value is not present.
# config.authentication_keys = [:email]
# Configure parameters from the request object used for authentication. Each entry
# given should be a request method and it will automatically be passed to the
# find_for_authentication method and considered in your model lookup. For instance,
# if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
# The same considerations mentioned for authentication_keys also apply to request_keys.
# config.request_keys = []
# Configure which authentication keys should be case-insensitive.
# These keys will be downcased upon creating or modifying a user and when used
# to authenticate or find a user. Default is :email.
config.case_insensitive_keys = [:email]
# Configure which authentication keys should have whitespace stripped.
# These keys will have whitespace before and after removed upon creating or
# modifying a user and when used to authenticate or find a user. Default is :email.
config.strip_whitespace_keys = [:email]
# Tell if authentication through request.params is enabled. True by default.
# It can be set to an array that will enable params authentication only for the
# given strategies, for example, `config.params_authenticatable = [:database]` will
# enable it only for database (email + password) authentication.
# config.params_authenticatable = true
# Tell if authentication through HTTP Auth is enabled. False by default.
# It can be set to an array that will enable http authentication only for the
# given strategies, for example, `config.http_authenticatable = [:database]` will
# enable it only for database authentication. The supported strategies are:
# :database = Support basic authentication with authentication key + password
# config.http_authenticatable = false
# If 401 status code should be returned for AJAX requests. True by default.
# config.http_authenticatable_on_xhr = true
# The realm used in Http Basic Authentication. 'Application' by default.
# config.http_authentication_realm = 'Application'
# It will change confirmation, password recovery and other workflows
# to behave the same regardless if the e-mail provided was right or wrong.
# Does not affect registerable.
# config.paranoid = true
# By default Devise will store the user in session. You can skip storage for
# particular strategies by setting this option.
# Notice that if you are skipping storage for all authentication paths, you
# may want to disable generating routes to Devise's sessions controller by
# passing skip: :sessions to `devise_for` in your config/routes.rb
config.skip_session_storage = [:http_auth]
# By default, Devise cleans up the CSRF token on authentication to
# avoid CSRF token fixation attacks. This means that, when using AJAX
# requests for sign in and sign up, you need to get a new CSRF token
# from the server. You can disable this option at your own risk.
# config.clean_up_csrf_token_on_authentication = true
# ==> Configuration for :database_authenticatable
# For bcrypt, this is the cost for hashing the password and defaults to 10. If
# using other encryptors, it sets how many times you want the password re-encrypted.
#
# Limiting the stretches to just one in testing will increase the performance of
# your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
# a value less than 10 in other environments. Note that, for bcrypt (the default
# encryptor), the cost increases exponentially with the number of stretches (e.g.
# a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation).
config.stretches = Rails.env.test? ? 1 : 10
# Setup a pepper to generate the encrypted password.
# config.pepper = '1dd38cee240f1b8caf5c7450a71fa6fc0053db3fc62d31706fcaf4b7135e03f616008ccc8124b934dedfd1d9b56306b441b9ef6cdd4a9f091355c0f2a4defa74'
# Send a notification email when the user's password is changed
# config.send_password_change_notification = false
# ==> Configuration for :confirmable
# A period that the user is allowed to access the website even without
# confirming their account. For instance, if set to 2.days, the user will be
# able to access the website for two days without confirming their account,
# access will be blocked just in the third day. Default is 0.days, meaning
# the user cannot access the website without confirming their account.
# config.allow_unconfirmed_access_for = 2.days
# A period that the user is allowed to confirm their account before their
# token becomes invalid. For example, if set to 3.days, the user can confirm
# their account within 3 days after the mail was sent, but on the fourth day
# their account can't be confirmed with the token any more.
# Default is nil, meaning there is no restriction on how long a user can take
# before confirming their account.
# config.confirm_within = 3.days
# If true, requires any email changes to be confirmed (exactly the same way as
# initial account confirmation) to be applied. Requires additional unconfirmed_email
# db field (see migrations). Until confirmed, new email is stored in
# unconfirmed_email column, and copied to email column on successful confirmation.
config.reconfirmable = true
# Defines which key will be used when confirming an account
# config.confirmation_keys = [:email]
# ==> Configuration for :rememberable
# The time the user will be remembered without asking for credentials again.
# config.remember_for = 2.weeks
# Invalidates all the remember me tokens when the user signs out.
config.expire_all_remember_me_on_sign_out = true
# If true, extends the user's remember period when remembered via cookie.
# config.extend_remember_period = false
# Options to be passed to the created cookie. For instance, you can set
# secure: true in order to force SSL only cookies.
# config.rememberable_options = {}
# ==> Configuration for :validatable
# Range for password length.
config.password_length = 4..72
# Email regex used to validate email formats. It simply asserts that
# one (and only one) @ exists in the given string. This is mainly
# to give user feedback and not to assert the e-mail validity.
# config.email_regexp = /\A[^@]+@[^@]+\z/
# ==> Configuration for :timeoutable
# The time you want to timeout the user session without activity. After this
# time the user will be asked for credentials again. Default is 30 minutes.
# config.timeout_in = 30.minutes
# ==> Configuration for :lockable
# Defines which strategy will be used to lock an account.
# :failed_attempts = Locks an account after a number of failed attempts to sign in.
# :none = No lock strategy. You should handle locking by yourself.
# config.lock_strategy = :failed_attempts
# Defines which key will be used when locking and unlocking an account
# config.unlock_keys = [:email]
# Defines which strategy will be used to unlock an account.
# :email = Sends an unlock link to the user email
# :time = Re-enables login after a certain amount of time (see :unlock_in below)
# :both = Enables both strategies
# :none = No unlock strategy. You should handle unlocking by yourself.
# config.unlock_strategy = :both
# Number of authentication tries before locking an account if lock_strategy
# is failed attempts.
# config.maximum_attempts = 20
# Time interval to unlock the account if :time is enabled as unlock_strategy.
# config.unlock_in = 1.hour
# Warn on the last attempt before the account is locked.
# config.last_attempt_warning = true
# ==> Configuration for :recoverable
#
# Defines which key will be used when recovering the password for an account
# config.reset_password_keys = [:email]
# Time interval you can reset your password with a reset password key.
# Don't put a too small interval or your users won't have the time to
# change their passwords.
config.reset_password_within = 6.hours
# When set to false, does not sign a user in automatically after their password is
# reset. Defaults to true, so a user is signed in automatically after a reset.
# config.sign_in_after_reset_password = true
# ==> Configuration for :encryptable
# Allow you to use another encryption algorithm besides bcrypt (default). You can use
# :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
# :authlogic_sha512 (then you should set stretches above to 20 for default behavior)
# and :restful_authentication_sha1 (then you should set stretches to 10, and copy
# REST_AUTH_SITE_KEY to pepper).
#
# Require the `devise-encryptable` gem when using anything other than bcrypt
# config.encryptor = :sha512
# ==> Scopes configuration
# Turn scoped views on. Before rendering "sessions/new", it will first check for
# "users/sessions/new". It's turned off by default because it's slower if you
# are using only default views.
# config.scoped_views = false
# Configure the default scope given to Warden. By default it's the first
# devise role declared in your routes (usually :user).
# config.default_scope = :user
# Set this configuration to false if you want /users/sign_out to sign out
# only the current scope. By default, Devise signs out all scopes.
# config.sign_out_all_scopes = true
# ==> Navigation configuration
# Lists the formats that should be treated as navigational. Formats like
# :html, should redirect to the sign in page when the user does not have
# access, but formats like :xml or :json, should return 401.
#
# If you have any extra navigational formats, like :iphone or :mobile, you
# should add them to the navigational formats lists.
#
# The "*/*" below is required to match Internet Explorer requests.
# config.navigational_formats = ['*/*', :html]
# The default HTTP method used to sign out a resource. Default is :delete.
config.sign_out_via = :delete
# ==> OmniAuth
# Add a new OmniAuth provider. Check the wiki for more information on setting
# up on your models and hooks.
# config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
# ==> Warden configuration
# If you want to use other strategies, that are not supported by Devise, or
# change the failure app, you can configure them inside the config.warden block.
#
# config.warden do |manager|
# manager.intercept_401 = false
# manager.default_strategies(scope: :user).unshift :some_external_strategy
# end
# ==> Mountable engine configurations
# When using Devise inside an engine, let's call it `MyEngine`, and this engine
# is mountable, there are some extra configurations to be taken into account.
# The following options are available, assuming the engine is mounted as:
#
# mount MyEngine, at: '/my_engine'
#
# The router that invoked `devise_for`, in the example above, would be:
# config.router_name = :my_engine
#
# When using OmniAuth, Devise cannot automatically set OmniAuth path,
# so you need to do it manually. For the users scope, it would be:
# config.omniauth_path_prefix = '/my_engine/users/auth'
end
================================================
FILE: config/initializers/filter_parameter_logging.rb
================================================
# Be sure to restart your server when you modify this file.
# Configure sensitive parameters which will be filtered from the log file.
Rails.application.config.filter_parameters += [:password]
================================================
FILE: config/initializers/inflections.rb
================================================
# Be sure to restart your server when you modify this file.
# Add new inflection rules using the following format. Inflections
# are locale specific, and you may define rules for as many different
# locales as you wish. All of these examples are active by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
# end
# These inflection rules are supported but not enabled by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.acronym 'RESTful'
# end
================================================
FILE: config/initializers/mime_types.rb
================================================
# Be sure to restart your server when you modify this file.
# Add new mime types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf
================================================
FILE: config/initializers/session_store.rb
================================================
# Be sure to restart your server when you modify this file.
Rails.application.config.session_store :cookie_store, key: '_chibineko_session'
================================================
FILE: config/initializers/time_formats.rb
================================================
================================================
FILE: config/initializers/wrap_parameters.rb
================================================
# Be sure to restart your server when you modify this file.
# This file contains settings for ActionController::ParamsWrapper which
# is enabled by default.
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
ActiveSupport.on_load(:action_controller) do
wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
end
# To enable root element in JSON for ActiveRecord objects.
# ActiveSupport.on_load(:active_record) do
# self.include_root_in_json = true
# end
================================================
FILE: config/locales/devise.en.yml
================================================
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
en:
devise:
confirmations:
confirmed: "Your email address has been successfully confirmed."
send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
failure:
already_authenticated: "You are already signed in."
inactive: "Your account is not activated yet."
invalid: "Invalid email or password."
locked: "Your account is locked."
last_attempt: "You have one more attempt before your account is locked."
not_found_in_database: "Invalid email or password."
timeout: "Your session expired. Please sign in again to continue."
unauthenticated: "You need to sign in or sign up before continuing."
unconfirmedX: "You have to confirm your email address before continuing."
mailer:
confirmation_instructions:
subject: "[Chibineko] Confirmation instructions"
reset_password_instructions:
subject: "[Chibineko] Reset password instructions"
unlock_instructions:
subject: "[Chibineko] Unlock instructions"
password_change:
subject: "[Chibineko] Password Changed"
omniauth_callbacks:
failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
success: "Successfully authenticated from %{kind} account."
passwords:
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
updated: "Your password has been changed successfully. You are now signed in."
updated_not_active: "Your password has been changed successfully."
registrations:
destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
signed_up: "Welcome! You have signed up successfully."
signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address."
updated: "Your account has been updated successfully."
sessions:
signed_in: "Signed in successfully."
signed_out: "Signed out successfully."
already_signed_out: "Signed out successfully."
unlocks:
send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
unlocked: "Your account has been unlocked successfully. Please sign in to continue."
errors:
messages:
already_confirmed: "was already confirmed, please try signing in"
confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
expired: "has expired, please request a new one"
not_found: "not found"
not_locked: "was not locked"
not_saved: "could not be processed"
================================================
FILE: config/locales/devise.ja.yml
================================================
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
ja:
devise:
confirmations:
confirmed: "メールアドレスの確認が完了しました"
send_instructions: "アカウントの有効化についてメールを送信しました"
send_paranoid_instructions: "あなたのメールアドレスが登録済みの場合、本人確認用のメールが数分以内に送信されます"
failure:
already_authenticated: "すでにログインしています"
inactive: "アカウントが有効化されていません。メールに記載された手順にしたがって、アカウントを有効化してください"
invalid: "メールアドレスもしくはパスワードが正しくありません"
locked: "あなたのアカウントは凍結されています"
last_attempt: "あなたのアカウントが凍結される前に、複数回の操作がおこなわれています"
not_found_in_database: "メールアドレスもしくはパスワードが正しくありません"
timeout: "セッションがタイムアウトしました。もう一度ログインしてください"
unauthenticated: "アカウント登録もしくはログインしてください"
unconfirmed: "メールアドレスの認証が完了していません。送信されたメールの内容を確認してください"
mailer:
confirmation_instructions:
subject: "[Chibineko] アカウントの有効化について"
reset_password_instructions:
subject: "[Chibineko] パスワードの再設定について"
unlock_instructions:
subject: "[Chibineko] アカウントの凍結解除について"
password_change:
subject: "[Chibineko] パスワードが変更されました"
omniauth_callbacks:
failure: "%{kind} アカウントによる認証に失敗しました。理由:(%{reason})"
success: "%{kind} アカウントによる認証に成功しました"
passwords:
no_token: "このページにはアクセスできません。パスワード再設定メールのリンクからアクセスされた場合には、URL をご確認ください"
send_instructions: "パスワードの再設定について数分以内にメールでご連絡いたします"
send_paranoid_instructions: "あなたのメールアドレスが登録済みの場合、パスワード再設定用のメールが数分以内に送信されます"
updated: "パスワードが正しく変更されました"
updated_not_active: "パスワードが正しく変更されました"
registrations:
destroyed: "アカウントを削除しました。またのご利用をお待ちしております"
signed_up: "アカウント登録が完了しました"
signed_up_but_inactive: "ログインするためには、アカウントを有効化してください"
signed_up_but_locked: "アカウントが凍結されているためログインできません"
signed_up_but_unconfirmed: "本人確認用のメールを送信しました。メール内のリンクからアカウントを有効化させてください"
update_needs_confirmation: "アカウント情報を変更しました。変更されたメールアドレスの本人確認のため、本人確認用メールより確認処理をおこなってください"
updated: "アカウント情報を変更しました"
sessions:
signed_in: "ログインしました"
signed_out: "ログアウトしました"
already_signed_out: "既にログアウト済みです"
unlocks:
send_instructions: "アカウントの凍結解除方法を数分以内にメールでご連絡します"
send_paranoid_instructions: "アカウントが見つかった場合、アカウントの凍結解除方法を数分以内にメールでご連絡します"
unlocked: "アカウントを凍結解除しました"
errors:
messages:
already_confirmed: "は既に登録済みです。ログインしてください"
confirmation_period_expired: "の期限が切れました。%{period} までに確認する必要があります。 新しくリクエストしてください"
expired: "の有効期限が切れました。新しくリクエストしてください"
not_found: "が見つかりませんでした"
not_locked: "は凍結されていません"
not_saved: "処理できませんでした"
================================================
FILE: config/locales/devise_view.en.yml
================================================
en:
devise:
registrations:
new:
sign_up: "Sign up"
not_receive: "Didn't receive confirmation instructions?"
confirmations:
new:
resend_confirmation: "Resend confirmation instructions"
send_mail: "Send mail"
sessions:
new:
sign_in: "Sign in"
remember_password: "Remember password"
passwords:
new:
forgot_password: "Forgot password"
send_mail: "Send mail"
================================================
FILE: config/locales/devise_view.ja.yml
================================================
ja:
devise:
registrations:
new:
sign_up: "ユーザー登録"
not_receive: "登録確認メールが届かない方はこちら"
confirmations:
new:
resend_confirmation: "登録確認メールを再送信"
send_mail: "メールを送信"
sessions:
new:
sign_in: "ログイン"
remember_password: "パスワードを忘れた場合はこちら"
passwords:
new:
forgot_password: "パスワードを再設定"
send_mail: "メールを送信"
================================================
FILE: config/locales/en.yml
================================================
en:
language_name: "English"
common:
created_by: "Created by"
updated_at: "Updated at"
updated_on: "Updated on"
dashboard: "Dashboard"
team: "Team"
project: "Project"
you: "You"
guest: "Guest user"
button:
new_team: "New team"
create_new_team: "Create a new team"
new_project: "New project"
create_new_project: "Create a new project"
new_test: "New test"
create_new_test: "Create a new test"
sign_in: "Sign in"
sign_out: "Sign out"
sign_up: "Sign up"
expand: "edit"
close: "close"
move: "Move"
delete: "Delete"
helpers:
submit:
create: "Create"
submit: "Save"
update: "Update"
test:
create: "Create test"
update: "Update test"
dialog:
done: "Done"
close: "Close"
cancel: "Cancel"
time:
formats:
default: "%a, %d %b %Y %H:%M:%S %z"
long: "%B %d, %Y %H:%M"
short: "%d %b %H:%M"
activerecord:
models:
user: "User"
team: "Team"
project: "Project"
attributes:
user:
email: "Email"
current_password: "Current password"
password: "Password"
password_confirmation: "Password confirmation"
name: "User name"
team:
name: "Team name"
project:
name: "Project name"
test:
title: "Title"
errors:
models:
team:
invalid: "may only contain letters (a-z), numbers, and underscores."
project:
invalid: "may only contain letters (a-z), numbers, and underscores."
messages:
too_short: "does not meet our requirements. (At least %{count} characters long)."
too_long: "does not meet our requirements. (At most %{count} characters long)."
taken: "has already been taken."
invalid: "is invalid."
confirmation: "doesn't match."
errors:
format: "%{attribute} %{message}"
forbidden: "You are not authorized to view this directory or page. Please contact team admin."
messages:
delete_confirm: "Are you sure? You can't undo the operation."
public_test_html: "This test can be accessed by anyone who knows the URL. Use the team features If you need to limit the access."
created_by_guest_html: "Because this test was created by a guest user, some features such as editing and deleting of the test items are limited."
please_association_html: "To user all features, log in and correlate to the user."
attach_current_user: "Correlate to the current user"
layouts:
navbar:
github_page: "GitHub page"
root_sidebar:
create_team: "Create a new team"
dashboard_sidebar:
your_test: "Your test"
coach_mark: "Create a team HERE !"
main_menu:
account_settings: "Account settings"
team_settings: "Team settings"
edit_members: "Edit team members"
static_pages:
top:
branding:
title: "The simplest test supporting tool"
sub_title: "Chibineko is a simple test supporting tool specializing in the management of manual tests"
get_started: "Get Started"
sign_up_free: "Sign Up for Free"
feature:
title: "Feature"
test_management_title: "Test Management"
test_management_body: "Chibineko supports your manual testing with its useful functions like test case creation, test execution, and progress management. Its simple design expands the usability in various situations."
team_management_title: "Team"
team_management_body: "With \"Team\" feature, you can share your test data among limited users. It enables you to secure your data information and manage test cases effectively."
share_result_title: "Share"
share_result_body: "Each test case has its individual URL. How do you share your test data with other users? All you need is to share the URL, you don't need to exchange any files any more."
oss_title: "OSS"
oss_body: "Our sourse code is available on GitHub. If you want to add some functions, feel free to extend. Issue and Pull Request will also be welcome."
support: "Support"
terms: "Terms of Service"
releases: "Releases"
roadmap: "Roadmap"
dashboard:
index:
title: "Dashboard"
navbar:
new_test: "Create a new test"
teams:
show:
empty_message: "No Projects"
new:
title: "New team"
enter_name: "Enter team name"
settings:
title: "Team settings"
name:
title: "Team name"
current_value_html: "Current team name: <strong>%{name}</strong>"
delete:
title: "Delete a team"
description: "When you delete a team, all of the related data such as projects and tests are also deleted."
delete_team: "Delete this team"
messages:
destroy: "The team has been successfully deleted."
team_users:
index:
title: "Edit team members"
search_user: "Search Chibineko user:"
add_user: "Add this user to the team"
delete_confirm: "Do you remove the user from the team members?"
projects:
navbar:
menu:
project_settings: "Project settings"
show:
empty_message: "No Tests"
new:
title: "New project"
enter_name: "Enter project name"
settings:
title: "Project settings"
name:
title: "Project name"
current_value_html: "Current project name:: <strong>%{name}</strong>"
delete:
title: "Delete a project"
description: "When you delete a project, all of the related tests are also deleted."
delete_project: "Delete this project"
messages:
destroy: "Project has been successfully deleted."
tests:
show:
blank_description: "No description"
created_by: "This test was created by %{username} (Updated at: %{updated_at})"
form:
title:
new: "Create a new test"
edit: "Edit test"
title_placeholder: "Enter test title"
markdown_header: "Test items"
markdown_placeholder: "Itemize test cases"
preview_header: "Preview"
description:
title: "Edit description"
testcase:
note: "Notes"
collapse_all: "Collapse all"
expand_all: "Expand all"
move:
title: "Move to"
unset_project: "No projects"
submit: "Move"
result_label:
title: "Customize result labels"
use_default_label: "Use the default labels"
label_placeholder: "Enter labels"
navbar:
edit_test: "Edit test"
edit_current_test: "Edit the current test"
export_csv: "Export CSV"
test_settings: "Test settings"
duplicate_test: "Duplicate this test"
move_to: "Move to"
customize_result_label: "Customize result labels"
delete_test: "Delete this test"
messages:
destroy: "The test has been successfully deleted."
result_labels:
unexecuted: "NOT RUN"
pass: "PASS"
fail: "FAIL"
blocked: "BLOCKED"
na: "N/A"
csv:
case: "Test cases"
result: "Results"
note: "Notes"
user_settings:
modal:
title: "Account settings"
expand: "edit"
close: "close"
username:
title: "User name"
blank: "E-mail address is used as an user name until a new name is entered."
current_value_html: "Your user name is <strong>%{username}</strong>"
password:
title: "Password"
change_password: "Change sign in password"
current_password: "Current password"
new_password: "New password"
confirm_password: "Confirm new password"
update: "Update Password"
timezone:
title: "Time Zone"
current_value_html: "Your current time zone: <strong>%{timezone}</strong>"
update: "Save Time Zone"
language:
title: "Language"
current_value_html: "Your current language: <strong>%{language}</strong>"
================================================
FILE: config/locales/ja.yml
================================================
ja:
language_name: "日本語"
common:
created_by: "作成者"
updated_at: "更新日時"
updated_on: "更新日"
dashboard: "ダッシュボード"
team: "チーム"
project: "プロジェクト"
you: "あなた"
guest: "ゲスト"
button:
new_team: "新規チーム"
create_new_team: "新しいチームを作成"
new_project: "新規プロジェクト"
create_new_project: "新しいプロジェクトを作成"
new_test: "新規テスト"
create_new_test: "新しいテストを作成"
sign_in: "ログイン"
sign_out: "ログアウト"
sign_up: "ユーザー登録"
expand: "編集"
close: "閉じる"
move: "移動"
delete: "削除"
helpers:
submit:
create: "作成"
submit: "保存"
update: "更新"
test:
create: "テストを作成"
update: "テストを更新"
dialog:
done: "完了"
close: "閉じる"
cancel: "キャンセル"
time:
formats:
default: "%Y/%m/%d %H:%M:%S"
long: "%Y年%m月%d日(%a) %H時%M分%S秒 %z"
short: "%y/%m/%d %H:%M"
activerecord:
models:
user: "ユーザー"
team: "チーム"
project: "プロジェクト"
attributes:
user:
email: "メールアドレス"
current_password: "現在のパスワード"
password: "パスワード"
password_confirmation: "パスワード(確認)"
name: "ユーザー名"
team:
name: "チーム名"
project:
name: "プロジェクト名"
test:
title: "タイトル"
errors:
models:
team:
invalid: "は半角英数字かアンダースコアで入力してください"
project:
invalid: "は半角英数字かアンダースコアで入力してください"
messages:
too_short: "は%{count}文字以上で入力してください"
too_long: "は%{count}文字以内で入力してください"
taken: "はすでに存在します"
invalid: "は不正な値です"
confirmation: "が一致しません"
errors:
format: "%{attribute}%{message}"
forbidden: "アクセスする権限がありません。チーム管理者に問い合わせてください。"
messages:
delete_confirm: "本当に削除しますか?この操作は取り消せません。"
public_test_html: "このテストは<strong>URLを知っているユーザーなら誰でもアクセスできます</strong>。アクセスできるユーザーを制限したい場合は<strong>チーム機能</strong>をご利用ください。"
created_by_guest_html: "このテストはゲストユーザーによって作成されたため、<strong>テスト項目の編集や削除など一部機能が制限</strong>されています。"
please_association_html: "すべての機能を使用したい場合は、ログインして<strong>ユーザーとの紐付け</strong>を行ってください。"
attach_current_user: "現在のユーザーに紐付ける"
layouts:
navbar:
github_page: "GitHubページ"
root_sidebar:
create_team: "新しいチームを作成"
dashboard_sidebar:
your_test: "あなたのテスト"
coach_mark: "チーム作成はこちら"
main_menu:
account_settings: "アカウント設定"
team_settings: "チーム設定"
edit_members: "チームメンバーを編集"
static_pages:
top:
branding:
title: "世界で最もシンプルなテスト支援ツール"
sub_title: "Chibinekoはマニュアルテストの管理に特化したシンプルなテストツールです"
get_started: "今すぐはじめる"
sign_up_free: "無料でサインアップ"
feature:
title: "機能"
test_management_title: "テスト管理"
test_management_body: "テストケース作成、テスト実行、進捗管理など、マニュアルテストに必要な一通りの機能を提供します。シンプルがゆえに自由度が高いため、様々なシーンで活用いただけます。"
team_management_title: "チーム管理"
team_management_body: "チームを作成してユーザーをアサインすれば、限られたユーザーのみでテスト内容を共有することができます。セキュリティを保ちつつ効率的にテストケースを管理することができます。"
share_result_title: "結果の共有"
share_result_body: "テストケースにはユニークなURLが割り当てられるため、他のユーザーとテスト結果を共有したい場合はURLをシェアするだけ。面倒なファイルのやり取りなどは不要です。"
oss_title: "OSS"
oss_body: "このサービスのソースコードはすべてGitHub上で公開されています。もし足りない機能がある場合は、自由に拡張してください。issueやPull Requestも歓迎します。"
support: "サポート"
terms: "利用規約"
releases: "リリースノート"
roadmap: "ロードマップ"
dashboard:
index:
title: "ダッシュボード"
navbar:
new_test: "新しいテストを作成"
teams:
show:
empty_message: "プロジェクトがまだありません"
new:
title: "新しいチーム"
enter_name: "チーム名を入力"
settings:
title: "チーム設定"
name:
title: "チーム名"
current_value_html: "現在のチーム名: <strong>%{name}</strong>"
delete:
title: "チームを削除"
description: "チームを削除すると、チームに含まれるプロジェクトおよびテストもすべて削除されます。"
delete_team: "このチームを削除する"
messages:
destroy: "チームを削除しました"
team_users:
index:
title: "チームメンバーを編集"
search_user: "Chibinekoユーザーを検索:"
add_user: "ユーザーをチームに追加"
delete_confirm: "チームメンバーから削除しますか?"
projects:
navbar:
menu:
project_settings: "プロジェクト設定"
show:
empty_message: "テストがまだありません"
new:
title: "新しいプロジェクト"
enter_name: "プロジェクト名を入力"
settings:
title: "プロジェクト設定"
name:
title: "プロジェクト名"
current_value_html: "現在のプロジェクト名: <strong>%{name}</strong>"
delete:
title: "プロジェクトを削除"
description: "プロジェクトを削除すると、プロジェクトに含まれるテストもすべて削除されます。"
delete_project: "このプロジェクトを削除する"
messages:
destroy: "プロジェクトを削除しました"
tests:
show:
blank_description: "説明が入力されていません"
created_by: "このテストは %{username} によって作成されました(更新日時: %{updated_at})"
form:
title:
new: "新しいテストを作成"
edit: "テストを編集"
title_placeholder: "タイトルを入力"
markdown_header: "テスト項目"
markdown_placeholder: "テスト項目を箇条書きで入力"
preview_header: "プレビュー"
description:
title: "説明を編集"
testcase:
note: "メモ"
collapse_all: "折りたたむ"
expand_all: "すべて展開"
move:
title: "テストを移動"
unset_project: "プロジェクト未設定"
submit: "移動"
result_label:
title: "結果ラベルをカスタマイズ"
use_default_label: "デフォルトラベルを使用"
label_placeholder: "ラベルを入力"
navbar:
edit_test: "テストを編集"
edit_current_test: "現在のテストを編集"
export_csv: "CSVエクスポート"
test_settings: "テスト設定"
duplicate_test: "このテストを複製"
move_to: "別プロジェクトへ移動"
customize_result_label: "結果ラベルをカスタマイズ"
delete_test: "このテストを削除"
messages:
destroy: "テストを削除しました"
result_labels:
unexecuted: "未実行"
pass: "OK"
fail: "NG"
blocked: "保留"
na: "対象外"
csv:
case: "テスト項目"
result: "結果"
note: "備考"
user_settings:
modal:
title: "アカウント設定"
expand: "編集"
close: "閉じる"
username:
title: "ユーザー名"
blank: "ユーザー名が未設定の場合、メールアドレスがユーザー名として表示されます"
current_value_html: "あなたのユーザー名: <strong>%{username}</strong>"
password:
title: "パスワード"
change_password: "ログインパスワードを変更します"
current_password: "現在のパスワード"
new_password: "新しいパスワード"
confirm_password: "新しいパスワード(確認)"
update: "パスワードを更新"
timezone:
title: "タイムゾーン"
current_value_html: "現在のタイムゾーン: <strong>%{timezone}</strong>"
update: "タイムゾーンを保存"
language:
title: "言語"
current_value_html: "現在の言語: <strong>%{language}</strong>"
================================================
FILE: config/locales/js.en.yml
================================================
en:
js:
team_sidebar:
edit_members:
search_user: "Search user..."
add_user: "Add this user to the team"
not_found: "User not found"
unknown_error: "Unknown error"
tests:
show:
errors:
conflict: "Test cases might have been editted by other uses."
please_reload: "Reload the page"
new:
messages:
unsaved_changes: "You have unsaved changes."
edit_result_label:
errors:
too_short: "You can not delete any more."
too_long: "You can not add any more."
navbar:
total: "Total"
toolbar:
selected: "selected"
bootgrid:
loading: "Loading..."
no_results: "No results found."
search: "Search by title"
common:
messages:
delete_confirm: "Are you sure? You can't undo the operation."
collapse:
expand: "edit"
close: "close"
ladda:
saving: "saving..."
processing: "processing..."
================================================
FILE: config/locales/js.ja.yml
================================================
ja:
js:
team_sidebar:
edit_members:
search_user: "検索中..."
add_user: "ユーザーをチームに追加"
not_found: "ユーザーが見つかりません"
unknown_error: "エラーが発生しました"
tests:
show:
errors:
conflict: "テスト項目が他のユーザーによって変更された可能性があります"
please_reload: "ページをリロードしてください"
new:
messages:
unsaved_changes: "変更内容が保存されていません。"
edit_result_label:
errors:
too_short: "これ以上削除できません。"
too_long: "これ以上追加できません。"
navbar:
total: "合計"
toolbar:
selected: "件選択中"
bootgrid:
loading: "読み込み中..."
no_results: "検索結果がありません"
search: "タイトルで検索"
common:
messages:
delete_confirm: "本当に削除しますか?この操作は取り消せません。"
collapse:
expand: "編集"
close: "閉じる"
ladda:
saving: "保存中..."
processing: "処理中..."
================================================
FILE: config/locales/terms.en.yml
================================================
en:
static_pages:
terms:
title: "Terms of Service"
body_html: |
<p>Last modified: January 20, 2015</p>
<h2>Article 1. Using our Services</h2>
<ol>
<li>These Terms and Conditions (the "Terms") set forth the terms between SHIFT Inc.(“SHIFT”) regarding the usage of the service under the name of "Chibineko" (the "Service") provided by SHIFT. The User shall use the Services in accordance with the contents of the Terms.</li>
<li>The Terms apply to all acts of Users in their use of the service.</li>
<li>Users are considered to have agreed to all the content stated in the Terms upon using the service.</li>
</ol>
<h2>Article 2. Definition</h2>
<ol>
<li>"Chibineko" means the WEB service (<a href="https://chibineko.jp">https://chibineko.jp</a>) that SHIFT owns and operates. Chibineko includes the followings:<br>
(a) similar or related Chibineko Website (including subdomain, different languages, widgets, smartphones, and so on), (b) a platform operated by SHIFT, (c) social plug ins, (d) software (e.g. toolbar), devices, and networks, existing or not-yet existing.</li>
<li>"The other Terms and regulations" mean agreements other than the Agreement that specify the Terms of the Services, regardless of their titles, including use agreements for fee-based services and use agreements for any other services.</li>
<li>"Platform" means a set of APIs and services (such as contents) that enable others, including application developers and website operators, to retrieve data from Chibineko or provide data to us.</li>
<li>"Information" mean facts and other information about you, including actions taken by Users and non-Users who interact with Chibineko.</li>
<li>"Development Information" means programs, contents and materials related to software, Web sites, applications or the like that Users of the Services or others involved with Chibineko use this Services to plan, develop, store and manage; records of development-related communication; information obtained by using any of the Services; facts or the like of their being engaged in development; and any other development-related facts or information.</li>
<li>"Other contents" mean every information posted by Users and the third parties, and it.</li>
<li>"User information" mean the information related to Users, development information, and all or a part of other contents.</li>
<li>"data" means any data, including a user's contents or information that you or a third party can retrieve from Chibineko or provide to Chibineko through Platform.</li>
<li>"post" means to post on Chibineko or otherwise make available by using Chibineko.</li>
<li>"use" means to use, run, copy, publicly perform or display, distribute, modify, translate, and create derivative works of.</li>
</ol>
<h2>Article 3. Scope of the Terms</h2>
<ol>
<li>The conditions of the Service use is published in the Terms and other Terms and regulations. The Other Terms of Use shall make-up a part of the Terms, regardless of the title.</li>
<li>If provisions of the Term and the other Terms (and regulations) are not consistent, the Term shall prevail the other Terms.</li>
</ol>
<h2>Article 4. Changes of the Terms</h2>
<ol>
<li>SHIFT reserves the right to change the Terms at its discretion without providing prior notice to Users.</li>
<li>The modification will become effective once the modified Terms are posted on an appropriate location within Chibineko Website, unless otherwise specified by SHIFT.</li>
<li>Users shall be deemed to have granted valid and irrevocable consent to the modified Terms by continuing to use the Service.</li>
</ol>
<h2>Article 5. Responsibility of Uses</h2>
<ol>
<li>SHIFT believes Users’ privacy is very important.</li>
<li>SHIFT handles personal information properly based on our <a href="http://www.shiftinc.jp/en/privacy/">privacy policy</a>.</li>
</ol>
<h2>Article 6. Preparation of Computer Environment</h2>
<ol>
<li>Users shall supply the necessary computer environment (hardware, software, data connection) for using the Service under Users' own responsibility and at Users' own expense.</li>
<li>Users shall, with its own costs and responsibilities, prepare and maintain security systems suitable for the Users' environment for use of the Service to avoid computer virus attacks, unauthorized access, information leakage, etc.</li>
<li>SHIFT will not be responsible for preparation of computer environment.</li>
</ol>
<h2>Article 7. Users' Responsibility</h2>
<ol>
<li>Users use this service on their own responsibility.</li>
<li>Users are responsible for all the information they provide to this service. SHIFT is not responsible for the information.</li>
<li>The User understands that SHIFT is not responsible for damages and loss of the data, and the User shall ta
gitextract_t1ykuj_k/
├── .gitignore
├── .rspec
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── app/
│ ├── assets/
│ │ ├── images/
│ │ │ └── .keep
│ │ ├── javascripts/
│ │ │ ├── application.coffee
│ │ │ ├── dashboards.coffee
│ │ │ ├── data_table.coffee
│ │ │ ├── move_tests.coffee
│ │ │ ├── projects.coffee
│ │ │ ├── static_pages.coffee
│ │ │ ├── team_users.coffee
│ │ │ ├── teams.coffee
│ │ │ ├── test_preview.coffee
│ │ │ ├── tests.coffee
│ │ │ └── validation.coffee
│ │ └── stylesheets/
│ │ ├── application.scss
│ │ ├── bootstrap_overrides.scss
│ │ ├── color.scss
│ │ ├── common.scss
│ │ ├── data_table.scss
│ │ ├── layouts/
│ │ │ ├── navbar.scss
│ │ │ ├── sidebar.scss
│ │ │ └── style.scss
│ │ ├── static_pages/
│ │ │ ├── terms.scss
│ │ │ └── top.scss
│ │ ├── teams/
│ │ │ └── team_users.scss
│ │ ├── tests/
│ │ │ ├── edit_result_label.scss
│ │ │ ├── form.scss
│ │ │ ├── move.scss
│ │ │ ├── show.scss
│ │ │ └── testcase.scss
│ │ ├── toastr_overrides.scss
│ │ └── vendor/
│ │ ├── best_in_place.scss
│ │ ├── bootgrid.scss
│ │ └── ladda.scss
│ ├── controllers/
│ │ ├── application_controller.rb
│ │ ├── concerns/
│ │ │ └── .keep
│ │ ├── dashboard_controller.rb
│ │ ├── projects_controller.rb
│ │ ├── static_pages_controller.rb
│ │ ├── team_users_controller.rb
│ │ ├── teams_controller.rb
│ │ ├── testcases_controller.rb
│ │ ├── tests_controller.rb
│ │ ├── user_settings_controller.rb
│ │ └── users/
│ │ └── registrations_controller.rb
│ ├── helpers/
│ │ ├── application_helper.rb
│ │ ├── dashboard_helper.rb
│ │ ├── projects_helper.rb
│ │ ├── static_pages_helper.rb
│ │ ├── team_users_helper.rb
│ │ ├── teams_helper.rb
│ │ └── tests_helper.rb
│ ├── mailers/
│ │ └── .keep
│ ├── models/
│ │ ├── .keep
│ │ ├── concerns/
│ │ │ └── .keep
│ │ ├── project.rb
│ │ ├── team.rb
│ │ ├── team_user.rb
│ │ ├── test.rb
│ │ ├── testcase.rb
│ │ └── user.rb
│ └── views/
│ ├── dashboard/
│ │ ├── _navbar.html.slim
│ │ └── index.html.slim
│ ├── devise/
│ │ ├── confirmations/
│ │ │ └── new.html.slim
│ │ ├── mailer/
│ │ │ ├── confirmation_instructions.en.html.slim
│ │ │ ├── confirmation_instructions.ja.html.slim
│ │ │ ├── password_change.html.erb
│ │ │ ├── reset_password_instructions.en.html.slim
│ │ │ └── reset_password_instructions.ja.html.slim
│ │ ├── passwords/
│ │ │ └── new.html.slim
│ │ ├── registrations/
│ │ │ └── new.html.slim
│ │ ├── sessions/
│ │ │ └── new.html.slim
│ │ └── shared/
│ │ └── _links.html.erb
│ ├── layouts/
│ │ ├── _dashboard_sidebar.html.slim
│ │ ├── _logo.html.slim
│ │ ├── _main_menu.html.slim
│ │ ├── _navbar.html.slim
│ │ ├── _root_sidebar.html.slim
│ │ ├── _sign_in_link.html.slim
│ │ ├── _sign_out_link.html.slim
│ │ ├── _sign_up_link.html.slim
│ │ ├── _team_sidebar.html.slim
│ │ └── application.html.slim
│ ├── projects/
│ │ ├── _navbar.html.slim
│ │ ├── _new.html.slim
│ │ ├── _save.js.erb
│ │ ├── _settings.html.slim
│ │ ├── create.js.erb
│ │ ├── new.js.erb
│ │ ├── settings.js.erb
│ │ ├── show.html.slim
│ │ └── update.js.erb
│ ├── static_pages/
│ │ ├── terms.html.slim
│ │ └── top.html.slim
│ ├── team_users/
│ │ ├── _index.html.slim
│ │ ├── _save.js.erb
│ │ ├── create.js.erb
│ │ ├── destroy.js.erb
│ │ └── index.js.erb
│ ├── teams/
│ │ ├── _new.html.slim
│ │ ├── _save.js.erb
│ │ ├── _settings.html.slim
│ │ ├── create.js.erb
│ │ ├── new.js.erb
│ │ ├── settings.js.erb
│ │ ├── show.html.slim
│ │ └── update.js.erb
│ ├── tests/
│ │ ├── _alert.html.slim
│ │ ├── _cheatsheet.en.html.slim
│ │ ├── _cheatsheet.ja.html.slim
│ │ ├── _description.html.slim
│ │ ├── _form.html.slim
│ │ ├── _move.html.slim
│ │ ├── _navbar.html.slim
│ │ ├── _result_label.html.slim
│ │ ├── _table_toolbar.html.slim
│ │ ├── _testcase.html.slim
│ │ ├── bulk_destroy.js.erb
│ │ ├── bulk_move.js.erb
│ │ ├── create.js.erb
│ │ ├── description.js.erb
│ │ ├── edit.html.slim
│ │ ├── move.js.erb
│ │ ├── new.html.slim
│ │ ├── result_label.js.erb
│ │ ├── show.csv.ruby
│ │ ├── show.html.slim
│ │ ├── update.js.erb
│ │ └── update_result_label.js.erb
│ └── user_settings/
│ ├── _modal.html.slim
│ ├── edit.js.erb
│ └── update.js.erb
├── bin/
│ ├── bundle
│ ├── rails
│ ├── rake
│ └── setup
├── circle.yml
├── config/
│ ├── application.rb
│ ├── boot.rb
│ ├── database.yml
│ ├── environment.rb
│ ├── environments/
│ │ ├── development.rb
│ │ ├── production.rb
│ │ └── test.rb
│ ├── i18n-js.yml
│ ├── initializers/
│ │ ├── action_mailer.rb
│ │ ├── assets.rb
│ │ ├── backtrace_silencers.rb
│ │ ├── cookies_serializer.rb
│ │ ├── devise.rb
│ │ ├── filter_parameter_logging.rb
│ │ ├── inflections.rb
│ │ ├── mime_types.rb
│ │ ├── session_store.rb
│ │ ├── time_formats.rb
│ │ └── wrap_parameters.rb
│ ├── locales/
│ │ ├── devise.en.yml
│ │ ├── devise.ja.yml
│ │ ├── devise_view.en.yml
│ │ ├── devise_view.ja.yml
│ │ ├── en.yml
│ │ ├── ja.yml
│ │ ├── js.en.yml
│ │ ├── js.ja.yml
│ │ ├── terms.en.yml
│ │ └── terms.ja.yml
│ ├── mailer.yml.example
│ ├── routes.rb
│ └── secrets.yml
├── config.ru
├── db/
│ ├── migrate/
│ │ ├── 20151224022612_devise_create_users.rb
│ │ ├── 20151224030646_create_teams.rb
│ │ ├── 20151225045046_create_projects.rb
│ │ ├── 20151225141534_create_tests.rb
│ │ ├── 20151226051709_create_testcases.rb
│ │ ├── 20160103121144_add_column_to_user.rb
│ │ ├── 20160109162956_create_team_users.rb
│ │ └── 20160319072222_add_created_at_index_to_test.rb
│ ├── schema.rb
│ └── seeds.rb
├── lib/
│ ├── assets/
│ │ └── .keep
│ └── tasks/
│ └── .keep
├── log/
│ └── .keep
├── public/
│ ├── 404.en.html
│ ├── 404.ja.html
│ ├── 422.en.html
│ ├── 422.ja.html
│ ├── 500.en.html
│ ├── 500.ja.html
│ ├── error.css
│ ├── javascripts/
│ │ └── translations.js
│ ├── maintenance.html
│ └── robots.txt
├── spec/
│ ├── factories/
│ │ ├── testcases.rb
│ │ └── tests.rb
│ ├── models/
│ │ ├── test_spec.rb
│ │ └── testcase_spec.rb
│ ├── rails_helper.rb
│ └── spec_helper.rb
└── vendor/
└── assets/
├── javascripts/
│ ├── .keep
│ └── jquery.readyselector.js
└── stylesheets/
└── .keep
SYMBOL INDEX (130 symbols across 32 files)
FILE: app/controllers/application_controller.rb
class ApplicationController (line 1) | class ApplicationController < ActionController::Base
class Forbidden (line 7) | class Forbidden < ActionController::ActionControllerError; end
method routing_error (line 9) | def routing_error
method forbidden_error (line 13) | def forbidden_error
method after_sign_in_path_for (line 17) | def after_sign_in_path_for(resource)
method format_error_message (line 21) | def format_error_message(object)
method set_locale (line 27) | def set_locale
method set_timezone (line 43) | def set_timezone
FILE: app/controllers/dashboard_controller.rb
class DashboardController (line 1) | class DashboardController < ApplicationController
method index (line 4) | def index
FILE: app/controllers/projects_controller.rb
class ProjectsController (line 1) | class ProjectsController < ApplicationController
method show (line 5) | def show
method new (line 9) | def new
method edit (line 13) | def edit
method create (line 16) | def create
method update (line 28) | def update
method destroy (line 34) | def destroy
method settings (line 39) | def settings
method set_project (line 43) | def set_project
method authorize! (line 49) | def authorize!
method project_params (line 54) | def project_params
FILE: app/controllers/static_pages_controller.rb
class StaticPagesController (line 1) | class StaticPagesController < ApplicationController
method top (line 2) | def top
method terms (line 6) | def terms
FILE: app/controllers/team_users_controller.rb
class TeamUsersController (line 1) | class TeamUsersController < ApplicationController
method index (line 4) | def index
method create (line 10) | def create
method destroy (line 19) | def destroy
method ajax_search_user (line 27) | def ajax_search_user
FILE: app/controllers/teams_controller.rb
class TeamsController (line 1) | class TeamsController < ApplicationController
method show (line 5) | def show
method new (line 11) | def new
method edit (line 15) | def edit
method create (line 18) | def create
method update (line 28) | def update
method destroy (line 34) | def destroy
method settings (line 39) | def settings
method set_team (line 43) | def set_team
method authorize! (line 48) | def authorize!
method team_params (line 53) | def team_params
FILE: app/controllers/testcases_controller.rb
class TestcasesController (line 1) | class TestcasesController < ApplicationController
method update (line 4) | def update
method set_testcase (line 14) | def set_testcase
method testcase_params (line 23) | def testcase_params
FILE: app/controllers/tests_controller.rb
class TestsController (line 1) | class TestsController < ApplicationController
method index (line 5) | def index
method show (line 9) | def show
method new (line 25) | def new
method edit (line 39) | def edit
method create (line 45) | def create
method update (line 63) | def update
method destroy (line 70) | def destroy
method description (line 82) | def description
method result_label (line 85) | def result_label
method update_result_label (line 88) | def update_result_label
method move (line 100) | def move
method bulk_move (line 104) | def bulk_move
method bulk_destroy (line 121) | def bulk_destroy
method user_association (line 130) | def user_association
method set_test (line 136) | def set_test
method authorize! (line 141) | def authorize!
method test_params (line 149) | def test_params
FILE: app/controllers/user_settings_controller.rb
class UserSettingsController (line 1) | class UserSettingsController < ApplicationController
method edit (line 5) | def edit
method update (line 8) | def update
method set_user (line 15) | def set_user
method user_params (line 19) | def user_params
FILE: app/controllers/users/registrations_controller.rb
class Users::RegistrationsController (line 1) | class Users::RegistrationsController < Devise::RegistrationsController
method edit (line 2) | def edit
method update (line 6) | def update
FILE: app/helpers/application_helper.rb
type ApplicationHelper (line 1) | module ApplicationHelper
function controller_action (line 2) | def controller_action
function color_names (line 6) | def color_names
function page_title (line 10) | def page_title(title)
FILE: app/helpers/dashboard_helper.rb
type DashboardHelper (line 1) | module DashboardHelper
FILE: app/helpers/projects_helper.rb
type ProjectsHelper (line 1) | module ProjectsHelper
function project_collection (line 2) | def project_collection
function current_project (line 6) | def current_project
FILE: app/helpers/static_pages_helper.rb
type StaticPagesHelper (line 1) | module StaticPagesHelper
FILE: app/helpers/team_users_helper.rb
type TeamUsersHelper (line 1) | module TeamUsersHelper
FILE: app/helpers/teams_helper.rb
type TeamsHelper (line 1) | module TeamsHelper
function current_team (line 2) | def current_team
FILE: app/helpers/tests_helper.rb
type TestsHelper (line 1) | module TestsHelper
function current_test (line 2) | def current_test
FILE: app/models/project.rb
class Project (line 1) | class Project < ActiveRecord::Base
method to_param (line 12) | def to_param
FILE: app/models/team.rb
class Team (line 1) | class Team < ActiveRecord::Base
method authorized? (line 14) | def authorized?(user)
method authorized! (line 18) | def authorized!(user)
method to_param (line 22) | def to_param
FILE: app/models/team_user.rb
class TeamUser (line 1) | class TeamUser < ActiveRecord::Base
FILE: app/models/test.rb
class Test (line 1) | class Test < ActiveRecord::Base
method to_param (line 12) | def to_param
method authorized? (line 16) | def authorized?(user)
method result_labels_or_default (line 24) | def result_labels_or_default
method result_label_texts (line 35) | def result_label_texts
method result_label_colors (line 39) | def result_label_colors
method testcase_groups (line 43) | def testcase_groups
method set_markdown (line 59) | def set_markdown(with_result = false)
method make_testcase (line 84) | def make_testcase
method set_slug (line 97) | def set_slug
method generate_slug (line 101) | def generate_slug
FILE: app/models/testcase.rb
class Testcase (line 1) | class Testcase < ActiveRecord::Base
method type (line 8) | def type
method result (line 19) | def result
method result_color (line 23) | def result_color
method heading_level (line 28) | def heading_level(text)
method body (line 39) | def body(text)
method result (line 54) | def result(text)
method note (line 62) | def note(text)
FILE: app/models/user.rb
class User (line 1) | class User < ActiveRecord::Base
method display_name (line 15) | def display_name
FILE: config/application.rb
type Chibineko (line 18) | module Chibineko
class Application (line 19) | class Application < Rails::Application
FILE: db/migrate/20151224022612_devise_create_users.rb
class DeviseCreateUsers (line 1) | class DeviseCreateUsers < ActiveRecord::Migration
method change (line 2) | def change
FILE: db/migrate/20151224030646_create_teams.rb
class CreateTeams (line 1) | class CreateTeams < ActiveRecord::Migration
method change (line 2) | def change
FILE: db/migrate/20151225045046_create_projects.rb
class CreateProjects (line 1) | class CreateProjects < ActiveRecord::Migration
method change (line 2) | def change
FILE: db/migrate/20151225141534_create_tests.rb
class CreateTests (line 1) | class CreateTests < ActiveRecord::Migration
method change (line 2) | def change
FILE: db/migrate/20151226051709_create_testcases.rb
class CreateTestcases (line 1) | class CreateTestcases < ActiveRecord::Migration
method change (line 2) | def change
FILE: db/migrate/20160103121144_add_column_to_user.rb
class AddColumnToUser (line 1) | class AddColumnToUser < ActiveRecord::Migration
method change (line 2) | def change
FILE: db/migrate/20160109162956_create_team_users.rb
class CreateTeamUsers (line 1) | class CreateTeamUsers < ActiveRecord::Migration
method change (line 2) | def change
FILE: db/migrate/20160319072222_add_created_at_index_to_test.rb
class AddCreatedAtIndexToTest (line 1) | class AddCreatedAtIndexToTest < ActiveRecord::Migration
method change (line 2) | def change
Condensed preview — 206 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (283K chars).
[
{
"path": ".gitignore",
"chars": 300,
"preview": "# Ignore bundler config.\n/.bundle\n/vendor/bundle\n\n# Ignore mailer config.\n/config/mailer.yml\n\n# Ignore the default SQLit"
},
{
"path": ".rspec",
"chars": 30,
"preview": "--color\n--require spec_helper\n"
},
{
"path": "Gemfile",
"chars": 1179,
"preview": "source 'https://rubygems.org'\n\nruby '2.3.0'\n\ngem 'rails', '4.2.4'\ngem 'slim-rails', '~> 3.0.0'\ngem 'sass-rails', '~> 5.0"
},
{
"path": "LICENSE",
"chars": 11410,
"preview": "Copyright 2016 SHIFT, Inc. All rights reserved.\n\n Apache License\n "
},
{
"path": "README.md",
"chars": 2531,
"preview": "# Chibineko\n[](https://circleci.com/gh/tabbyz/chib"
},
{
"path": "Rakefile",
"chars": 249,
"preview": "# Add your own tasks in files placed in lib/tasks ending in .rake,\n# for example lib/tasks/capistrano.rake, and they wil"
},
{
"path": "app/assets/images/.keep",
"chars": 0,
"preview": ""
},
{
"path": "app/assets/javascripts/application.coffee",
"chars": 1129,
"preview": "#= require jquery\n#= require jquery_ujs\n#= require jquery.cookie\n#= require jstz\n#= require browser_timezone_rails/set_t"
},
{
"path": "app/assets/javascripts/dashboards.coffee",
"chars": 0,
"preview": ""
},
{
"path": "app/assets/javascripts/data_table.coffee",
"chars": 2006,
"preview": "$(document).ready ->\n # Bootgrid settings\n $(\".data-table\").on(\"initialized.rs.jquery.bootgrid\", (e) ->\n $(\".table-"
},
{
"path": "app/assets/javascripts/move_tests.coffee",
"chars": 276,
"preview": "$(\".tests.show\").ready ->\n \n $(document).on \"click\", \".move-test-modal .clickable\", ->\n $(\".project-list .clickable"
},
{
"path": "app/assets/javascripts/projects.coffee",
"chars": 0,
"preview": ""
},
{
"path": "app/assets/javascripts/static_pages.coffee",
"chars": 211,
"preview": "# Place all the behaviors and hooks related to the matching controller here.\n# All this logic will automatically be avai"
},
{
"path": "app/assets/javascripts/team_users.coffee",
"chars": 1571,
"preview": "$(\".projects, .teams, .tests\").ready ->\n# ==================================================\n# Function\n# =============="
},
{
"path": "app/assets/javascripts/teams.coffee",
"chars": 0,
"preview": ""
},
{
"path": "app/assets/javascripts/test_preview.coffee",
"chars": 3366,
"preview": "$(\".tests.new, .tests.edit\").ready ->\n# ==================================================\n# Function\n# ================"
},
{
"path": "app/assets/javascripts/tests.coffee",
"chars": 6722,
"preview": "$(\".tests.show\").ready ->\n# ==================================================\n# Function\n# ============================"
},
{
"path": "app/assets/javascripts/validation.coffee",
"chars": 1267,
"preview": "$(document).ready ->\n $(document).on \"keydown\", \".form-control.validation\", (e) ->\n if (e.keyCode != 13)\n $(thi"
},
{
"path": "app/assets/stylesheets/application.scss",
"chars": 332,
"preview": "/*\n *= require_tree .\n *= require_self\n */\n\n@import \"bootstrap-sprockets\";\n@import \"bootstrap\";\n@import \"bootstrap_overr"
},
{
"path": "app/assets/stylesheets/bootstrap_overrides.scss",
"chars": 1019,
"preview": "a {\n &:hover, &:focus {\n text-decoration: none;\n }\n}\n\ntextarea {\n resize: none;\n}\n\n.btn, .form-control {\n border-"
},
{
"path": "app/assets/stylesheets/color.scss",
"chars": 4151,
"preview": "// http://www.materialui.co/colors\n// background-color: 400\n// background-color(hover): 500\n// border-color: "
},
{
"path": "app/assets/stylesheets/common.scss",
"chars": 3099,
"preview": ".modal-fullscreen {\n width: 100% !important;\n height: 100% !important;\n margin: 0 !important;\n padding: 20px;\n\n .mo"
},
{
"path": "app/assets/stylesheets/data_table.scss",
"chars": 233,
"preview": ".actionBar .table-toolbar {\n display: inline-block;\n float: right;\n\n .selected-count {\n display: inline-block;\n "
},
{
"path": "app/assets/stylesheets/layouts/navbar.scss",
"chars": 766,
"preview": ".navbar {\n background-color: #FFF;\n \n > .container-fluid {\n margin-top: 7px;\n }\n\n .navbar-nav > li > a {\n pad"
},
{
"path": "app/assets/stylesheets/layouts/sidebar.scss",
"chars": 3380,
"preview": ".page-with-sidebar {\n .sidebar {\n display: -webkit-flex;\n display: flex;\n -webkit-flex-direction: column;\n "
},
{
"path": "app/assets/stylesheets/layouts/style.scss",
"chars": 1086,
"preview": "body, html {\n width: 100%;\n height: 100%;\n}\n\nbody {\n -webkit-text-size-adjust: 100%;\n margin: 0;\n}\n\nbody {\n &.regis"
},
{
"path": "app/assets/stylesheets/static_pages/terms.scss",
"chars": 135,
"preview": ".terms {\n h1 {\n margin-top: 0;\n }\n\n h2 {\n margin-top: 30px;\n padding-bottom: 10px;\n border-bottom: 1px so"
},
{
"path": "app/assets/stylesheets/static_pages/top.scss",
"chars": 3495,
"preview": ".static_pages.top {\n .navbar {\n background-color: #01AB52;\n box-shadow: none;\n margin-bottom: 0;\n border-ra"
},
{
"path": "app/assets/stylesheets/teams/team_users.scss",
"chars": 417,
"preview": ".team-users-modal {\n .search-user {\n text-align: center;\n \n width: 300px;\n margin: 0 auto;\n margin-botto"
},
{
"path": "app/assets/stylesheets/tests/edit_result_label.scss",
"chars": 1463,
"preview": ".edit-result-label-modal {\n .popover-content-template {\n display: none;\n }\n\n .checkbox {\n margin-left: 8px;\n }"
},
{
"path": "app/assets/stylesheets/tests/form.scss",
"chars": 1934,
"preview": ".tests.new, .tests.edit {\n .contents {\n position: relative;\n \n .test-title {\n position: absolute;\n lef"
},
{
"path": "app/assets/stylesheets/tests/move.scss",
"chars": 673,
"preview": ".move-test-modal {\n .project-list {\n .unset-project {\n padding: 5px 7px;\n font-weight: bold;\n }\n\n .t"
},
{
"path": "app/assets/stylesheets/tests/show.scss",
"chars": 1437,
"preview": ".tests.show {\n .progress-count-list {\n margin-bottom: 0;\n td {\n text-align: right;\n padding: 4px;\n\n "
},
{
"path": "app/assets/stylesheets/tests/testcase.scss",
"chars": 2413,
"preview": ".testcase-list {\n .testcase-group {\n background-color: #FFF;\n border: 1px solid #DDD;\n border-top-style: none;"
},
{
"path": "app/assets/stylesheets/toastr_overrides.scss",
"chars": 137,
"preview": "#toast-container > div {\n opacity: 1.0;\n}\n\n.toast-info {\n background-color: #4CAF50;\n}\n\n.toast-warning {\n background-"
},
{
"path": "app/assets/stylesheets/vendor/best_in_place.scss",
"chars": 426,
"preview": ".best_in_place {\n display: block;\n width: 100%;\n padding: 4px;\n border: 1px solid transparent;\n border-radius: 2px;"
},
{
"path": "app/assets/stylesheets/vendor/bootgrid.scss",
"chars": 486,
"preview": ".bootgrid-header {\n margin-top: 0;\n\n .actionBar {\n padding-left: 0;\n padding-right: 0;\n text-align: left;\n\n "
},
{
"path": "app/assets/stylesheets/vendor/ladda.scss",
"chars": 172,
"preview": ".ladda-button {\n &:disabled {\n cursor: default;\n }\n\n &[data-loading=\"\"] .ladda-spinner {\n top: 50% !important;\n"
},
{
"path": "app/controllers/application_controller.rb",
"chars": 1434,
"preview": "class ApplicationController < ActionController::Base\n # Prevent CSRF attacks by raising an exception.\n # For APIs, you"
},
{
"path": "app/controllers/concerns/.keep",
"chars": 0,
"preview": ""
},
{
"path": "app/controllers/dashboard_controller.rb",
"chars": 180,
"preview": "class DashboardController < ApplicationController\n before_action :authenticate_user!\n \n def index\n @tests = curren"
},
{
"path": "app/controllers/projects_controller.rb",
"chars": 1290,
"preview": "class ProjectsController < ApplicationController\n before_action :authenticate_user!\n before_action :authorize!, except"
},
{
"path": "app/controllers/static_pages_controller.rb",
"chars": 112,
"preview": "class StaticPagesController < ApplicationController\n def top\n @user = User.new\n end\n\n def terms\n end\nend\n"
},
{
"path": "app/controllers/team_users_controller.rb",
"chars": 834,
"preview": "class TeamUsersController < ApplicationController\n before_action :authenticate_user!\n\n def index\n @team = Team.find"
},
{
"path": "app/controllers/teams_controller.rb",
"chars": 1176,
"preview": "class TeamsController < ApplicationController\n before_action :authenticate_user!\n before_action :authorize!, except: ["
},
{
"path": "app/controllers/testcases_controller.rb",
"chars": 748,
"preview": "class TestcasesController < ApplicationController\n before_action :set_testcase, only: [:update]\n\n def update\n test"
},
{
"path": "app/controllers/tests_controller.rb",
"chars": 3922,
"preview": "class TestsController < ApplicationController\n before_action :authenticate_user!, except: [:show]\n before_action :auth"
},
{
"path": "app/controllers/user_settings_controller.rb",
"chars": 462,
"preview": "class UserSettingsController < ApplicationController\n before_action :authenticate_user!\n before_action :set_user, only"
},
{
"path": "app/controllers/users/registrations_controller.rb",
"chars": 1025,
"preview": "class Users::RegistrationsController < Devise::RegistrationsController\n def edit\n routing_error # Invalidate a \"/us"
},
{
"path": "app/helpers/application_helper.rb",
"chars": 432,
"preview": "module ApplicationHelper\n def controller_action\n controller_name + \"#\" + action_name\n end\n\n def color_names\n %w"
},
{
"path": "app/helpers/dashboard_helper.rb",
"chars": 27,
"preview": "module DashboardHelper\nend\n"
},
{
"path": "app/helpers/projects_helper.rb",
"chars": 388,
"preview": "module ProjectsHelper\n def project_collection\n current_team.projects if current_team\n end\n\n def current_project\n "
},
{
"path": "app/helpers/static_pages_helper.rb",
"chars": 29,
"preview": "module StaticPagesHelper\nend\n"
},
{
"path": "app/helpers/team_users_helper.rb",
"chars": 27,
"preview": "module TeamUsersHelper\nend\n"
},
{
"path": "app/helpers/teams_helper.rb",
"chars": 217,
"preview": "module TeamsHelper\n def current_team\n if team_name = params[:name] || params[:team_name]\n Team.find_by(name: te"
},
{
"path": "app/helpers/tests_helper.rb",
"chars": 86,
"preview": "module TestsHelper\n def current_test\n Test.find_by(slug: params[:slug])\n end\nend\n"
},
{
"path": "app/mailers/.keep",
"chars": 0,
"preview": ""
},
{
"path": "app/models/.keep",
"chars": 0,
"preview": ""
},
{
"path": "app/models/concerns/.keep",
"chars": 0,
"preview": ""
},
{
"path": "app/models/project.rb",
"chars": 382,
"preview": "class Project < ActiveRecord::Base\n belongs_to :team\n has_many :tests, :dependent => :destroy\n before_save { self.nam"
},
{
"path": "app/models/team.rb",
"chars": 646,
"preview": "class Team < ActiveRecord::Base\n has_many :projects, :dependent => :destroy\n has_many :team_users, :dependent => :dest"
},
{
"path": "app/models/team_user.rb",
"chars": 114,
"preview": "class TeamUser < ActiveRecord::Base\n belongs_to :team\n belongs_to :user\n default_scope { order(\"id ASC\") }\nend\n"
},
{
"path": "app/models/test.rb",
"chars": 2406,
"preview": "class Test < ActiveRecord::Base\n belongs_to :user\n belongs_to :project\n has_many :testcases, dependent: :destroy\n af"
},
{
"path": "app/models/testcase.rb",
"chars": 1385,
"preview": "class Testcase < ActiveRecord::Base\n belongs_to :test\n validates :body, length: { maximum: 1024 }\n validates :result,"
},
{
"path": "app/models/user.rb",
"chars": 571,
"preview": "class User < ActiveRecord::Base\n has_many :tests\n has_many :team_users\n has_many :teams, :through => :team_users\n va"
},
{
"path": "app/views/dashboard/_navbar.html.slim",
"chars": 365,
"preview": "nav.navbar.navbar-fixed-top.navbar-with-sidebar\n .navbar-content\n = link_to fa_icon(\"plus\", text: t(\"common.button.n"
},
{
"path": "app/views/dashboard/index.html.slim",
"chars": 1267,
"preview": "- provide :title, t(\"dashboard.index.title\")\n\n= render \"navbar\"\n\n- if @tests.size == 0\n .empty-data\n = fa_icon(\"inbo"
},
{
"path": "app/views/devise/confirmations/new.html.slim",
"chars": 645,
"preview": "- if devise_error_messages!.present?\n .card.card-alert = devise_error_messages!\n\n.card.card-form\n = form_for(resource,"
},
{
"path": "app/views/devise/mailer/confirmation_instructions.en.html.slim",
"chars": 178,
"preview": "p = \"Welcome #{@email} !\"\n\np You can confirm your account email through the link below:\n\np = link_to \"Confirm my account"
},
{
"path": "app/views/devise/mailer/confirmation_instructions.ja.html.slim",
"chars": 140,
"preview": "p = \"ようこそ #{@email} さん。\"\n\np 下記のリンクをクリックして、ユーザ登録を完了してください。\n\np = link_to \"メールアドレスを認証\", confirmation_url(@resource, confirm"
},
{
"path": "app/views/devise/mailer/password_change.html.erb",
"chars": 117,
"preview": "<p>Hello <%= @resource.email %>!</p>\n\n<p>We're contacting you to notify you that your password has been changed.</p>\n"
},
{
"path": "app/views/devise/mailer/reset_password_instructions.en.html.slim",
"chars": 363,
"preview": "p = \"Hello #{@resource.email} !\"\n\np Someone has requested a link to change your password. You can do this through the li"
},
{
"path": "app/views/devise/mailer/reset_password_instructions.ja.html.slim",
"chars": 254,
"preview": "p = \"こんにちは #{@resource.email} さん。\"\n\np パスワードリセットのリクエストが行われました。<br>下記のリンクからパスワードを変更することができます。\n\np = link_to \"パスワードを再設定\", ed"
},
{
"path": "app/views/devise/passwords/new.html.slim",
"chars": 549,
"preview": "- if devise_error_messages!.present?\n .card.card-alert = devise_error_messages!\n\n.card.card-form\n = form_for(resource,"
},
{
"path": "app/views/devise/registrations/new.html.slim",
"chars": 1002,
"preview": "- if devise_error_messages!.present?\n .card.card-alert = devise_error_messages!\n\n.card.card-form\n = form_for(resource,"
},
{
"path": "app/views/devise/sessions/new.html.slim",
"chars": 670,
"preview": ".card.card-form\n = form_for(resource, as: resource_name, url: session_path(resource_name)) do |f|\n h1.card-title = t"
},
{
"path": "app/views/devise/shared/_links.html.erb",
"chars": 1149,
"preview": "<%- if controller_name != 'sessions' %>\n <%= link_to \"Log in\", new_session_path(resource_name) %><br />\n<% end -%>\n\n<%-"
},
{
"path": "app/views/layouts/_dashboard_sidebar.html.slim",
"chars": 538,
"preview": ".sidebar.team-sidebar\n .sidebar-title.dropdown\n a.dropdown-toggle aria-expanded=\"false\" aria-haspopup=\"true\" data-to"
},
{
"path": "app/views/layouts/_logo.html.slim",
"chars": 48,
"preview": "/ = link_to \"Chibineko\", root_url, class: \"logo\""
},
{
"path": "app/views/layouts/_main_menu.html.slim",
"chars": 504,
"preview": "ul.dropdown-menu style=\"top: 44px; left: 18px;\"\n li.dropdown-header = t(\"common.you\")\n li = link_to fa_icon(\"cog\", tex"
},
{
"path": "app/views/layouts/_navbar.html.slim",
"chars": 1112,
"preview": "- if controller_action == \"static_pages#top\"\n nav.navbar\n .container-fluid\n = link_to \"Chibineko\", root_url, cl"
},
{
"path": "app/views/layouts/_root_sidebar.html.slim",
"chars": 815,
"preview": ".sidebar.root-sidebar\n = link_to fa_icon(\"home 2x\"), dashboard_path, class: \"home-btn\", data: { toggle: \"tooltip\", plac"
},
{
"path": "app/views/layouts/_sign_in_link.html.slim",
"chars": 59,
"preview": "= link_to t(\"common.button.sign_in\"), new_user_session_path"
},
{
"path": "app/views/layouts/_sign_out_link.html.slim",
"chars": 108,
"preview": "= link_to fa_icon(\"sign-out\", text: t(\"common.button.sign_out\")), destroy_user_session_path, method: :delete"
},
{
"path": "app/views/layouts/_sign_up_link.html.slim",
"chars": 97,
"preview": "= link_to t(\"common.button.sign_up\"), new_user_registration_path, class: \"btn color-blue sign-up\""
},
{
"path": "app/views/layouts/_team_sidebar.html.slim",
"chars": 841,
"preview": ".sidebar.team-sidebar\n .sidebar-title.dropdown\n a.dropdown-toggle aria-expanded=\"false\" aria-haspopup=\"true\" data-to"
},
{
"path": "app/views/layouts/application.html.slim",
"chars": 1302,
"preview": "doctype html\nhtml\n head\n title = page_title(yield :title)\n - if controller_action == \"static_pages#top\"\n met"
},
{
"path": "app/views/projects/_navbar.html.slim",
"chars": 810,
"preview": "nav.navbar.navbar-fixed-top.navbar-with-sidebar\n .navbar-content\n .navbar-title\n .dropdown\n a.dropdown-t"
},
{
"path": "app/views/projects/_new.html.slim",
"chars": 697,
"preview": ".new-project-modal.modal-dialog.modal-sm\n .modal-content\n = form_for @project, url: team_projects_path, remote: true"
},
{
"path": "app/views/projects/_save.js.erb",
"chars": 115,
"preview": "$(\".modal\").modal(\"hide\")\n$(window.location.replace(\"<%= team_project_path(@project.team.name, @project.name) %>\"))"
},
{
"path": "app/views/projects/_settings.html.slim",
"chars": 1751,
"preview": ".project-settings-modal.modal-dialog\n .modal-content\n .modal-header\n button.close type=\"button\" data-dismiss=\"m"
},
{
"path": "app/views/projects/create.js.erb",
"chars": 20,
"preview": "<%= render 'save' %>"
},
{
"path": "app/views/projects/new.js.erb",
"chars": 84,
"preview": "$(\".modal\").html(\"<%= escape_javascript(render 'new') %>\")\n$(\".modal\").modal(\"show\")"
},
{
"path": "app/views/projects/settings.js.erb",
"chars": 117,
"preview": "$(\".modal\").html(\"<%= escape_javascript(render 'settings') %>\")\nLadda.bind(\".ladda-button\")\n$(\".modal\").modal(\"show\")"
},
{
"path": "app/views/projects/show.html.slim",
"chars": 1334,
"preview": "- provide :title, \"#{@project.team.name}##{@project.name}\"\n\n= render \"navbar\"\n\n- if @project.tests.size == 0\n .empty-da"
},
{
"path": "app/views/projects/update.js.erb",
"chars": 20,
"preview": "<%= render 'save' %>"
},
{
"path": "app/views/static_pages/terms.html.slim",
"chars": 79,
"preview": ".card.card-lg\n h1.card-title = t(\".title\")\n\n .card-body\n = t(\".body_html\")"
},
{
"path": "app/views/static_pages/top.html.slim",
"chars": 3014,
"preview": ".container-fluid\n .row.branding.text-center\n h1 = t(\".branding.title\")\n p = t(\".branding.sub_title\")\n\n - if us"
},
{
"path": "app/views/team_users/_index.html.slim",
"chars": 1627,
"preview": ".team-users-modal.modal-dialog.modal-sm\n .modal-content\n .modal-header\n button.close type=\"button\" data-dismiss"
},
{
"path": "app/views/team_users/_save.js.erb",
"chars": 88,
"preview": "$(\".modal\").html(\"<%= escape_javascript(render 'index') %>\")\nLadda.bind(\".ladda-button\")"
},
{
"path": "app/views/team_users/create.js.erb",
"chars": 20,
"preview": "<%= render 'save' %>"
},
{
"path": "app/views/team_users/destroy.js.erb",
"chars": 20,
"preview": "<%= render 'save' %>"
},
{
"path": "app/views/team_users/index.js.erb",
"chars": 114,
"preview": "$(\".modal\").html(\"<%= escape_javascript(render 'index') %>\")\nLadda.bind(\".ladda-button\")\n$(\".modal\").modal(\"show\")"
},
{
"path": "app/views/teams/_new.html.slim",
"chars": 666,
"preview": ".new-team-modal.modal-dialog.modal-sm\n .modal-content\n = form_for @team, remote: true do |f|\n .modal-header\n "
},
{
"path": "app/views/teams/_save.js.erb",
"chars": 84,
"preview": "$(\".modal\").modal(\"hide\")\n$(window.location.replace(\"<%= team_path(@team.name) %>\"))"
},
{
"path": "app/views/teams/_settings.html.slim",
"chars": 1660,
"preview": ".team-settings-modal.modal-dialog\n .modal-content\n .modal-header\n button.close type=\"button\" data-dismiss=\"moda"
},
{
"path": "app/views/teams/create.js.erb",
"chars": 20,
"preview": "<%= render 'save' %>"
},
{
"path": "app/views/teams/new.js.erb",
"chars": 84,
"preview": "$(\".modal\").html(\"<%= escape_javascript(render 'new') %>\")\n$(\".modal\").modal(\"show\")"
},
{
"path": "app/views/teams/settings.js.erb",
"chars": 117,
"preview": "$(\".modal\").html(\"<%= escape_javascript(render 'settings') %>\")\nLadda.bind(\".ladda-button\")\n$(\".modal\").modal(\"show\")"
},
{
"path": "app/views/teams/show.html.slim",
"chars": 317,
"preview": "- provide :title, @team.name\n\n- if @team.projects.size == 0\n .empty-data\n = fa_icon(\"inbox\", class: \"symbol\")\n h3"
},
{
"path": "app/views/teams/update.js.erb",
"chars": 20,
"preview": "<%= render 'save' %>"
},
{
"path": "app/views/tests/_alert.html.slim",
"chars": 393,
"preview": "- if @test.user && @test.project.nil?\n .alert.alert-info\n p = t(\"messages.public_test_html\")\n\n- if @test.user.nil?\n "
},
{
"path": "app/views/tests/_cheatsheet.en.html.slim",
"chars": 601,
"preview": ".cheatsheet\n p.cheatsheet-header = fa_icon(\"question-circle\", text: \"Tips: how to create test cases\")\n .cheatsheet-blo"
},
{
"path": "app/views/tests/_cheatsheet.ja.html.slim",
"chars": 389,
"preview": ".cheatsheet\n p.cheatsheet-header = fa_icon(\"question-circle\", text: \"書き方のヒント\")\n .cheatsheet-block\n p.cheatsheet-tit"
},
{
"path": "app/views/tests/_description.html.slim",
"chars": 607,
"preview": ".edit-description-modal.modal-dialog.modal-lg\n .modal-content\n = form_for @test, remote: true do |f|\n .modal-he"
},
{
"path": "app/views/tests/_form.html.slim",
"chars": 911,
"preview": "= render \"navbar\"\n\n= form_for @test, remote: true do |f|\n = f.hidden_field :source\n = f.hidden_field :team_name, value"
},
{
"path": "app/views/tests/_move.html.slim",
"chars": 1022,
"preview": ".move-test-modal.modal-dialog.modal-xs\n .modal-content\n = form_for @test, remote: true do |f|\n = f.hidden_field"
},
{
"path": "app/views/tests/_navbar.html.slim",
"chars": 2133,
"preview": "nav.navbar.navbar-fixed-top.navbar-with-sidebar\n .navbar-content\n - if action_name == \"show\"\n = link_to fa_icon"
},
{
"path": "app/views/tests/_result_label.html.slim",
"chars": 2055,
"preview": ".edit-result-label-modal.modal-dialog.modal-xs\n .modal-content\n = form_for @test, url: update_result_label_test_path"
},
{
"path": "app/views/tests/_table_toolbar.html.slim",
"chars": 734,
"preview": ".table-toolbar\n span.selected-count\n ul.nav.navbar-nav.navbar-right\n li = link_to fa_icon(\"trash-o\", text: t(\"commo"
},
{
"path": "app/views/tests/_testcase.html.slim",
"chars": 1741,
"preview": ".testcase-toolbar\n button type=\"button\" class=\"btn-link js-collapse-all-btn\"\n = fa_icon \"caret-down\", text: t(\".coll"
},
{
"path": "app/views/tests/bulk_destroy.js.erb",
"chars": 24,
"preview": "window.location.reload()"
},
{
"path": "app/views/tests/bulk_move.js.erb",
"chars": 24,
"preview": "window.location.reload()"
},
{
"path": "app/views/tests/create.js.erb",
"chars": 84,
"preview": "$(\".modal\").modal(\"hide\")\n$(window.location.replace(\"<%= test_path(@test.slug) %>\"))"
},
{
"path": "app/views/tests/description.js.erb",
"chars": 92,
"preview": "$(\".modal\").html(\"<%= escape_javascript(render 'description') %>\")\n$(\".modal\").modal(\"show\")"
},
{
"path": "app/views/tests/edit.html.slim",
"chars": 15,
"preview": "= render \"form\""
},
{
"path": "app/views/tests/move.js.erb",
"chars": 85,
"preview": "$(\".modal\").html(\"<%= escape_javascript(render 'move') %>\")\n$(\".modal\").modal(\"show\")"
},
{
"path": "app/views/tests/new.html.slim",
"chars": 15,
"preview": "= render \"form\""
},
{
"path": "app/views/tests/result_label.js.erb",
"chars": 254,
"preview": "$(\".modal\").html(\"<%= escape_javascript(render 'result_label') %>\")\n$(\".modal\").modal(\"show\")\n\nSortable.create(resultLab"
},
{
"path": "app/views/tests/show.csv.ruby",
"chars": 924,
"preview": "require 'csv'\n\ntestcases = @test.testcases\n\n# Examine the maximum heading level\nmax_level = 0\ntestcases.each do |c|\n if"
},
{
"path": "app/views/tests/show.html.slim",
"chars": 1057,
"preview": "- provide :title, @test.title\n\n- if !user_signed_in?\n = render \"layouts/navbar\"\n- else\n = render \"navbar\"\n\n.progress.p"
},
{
"path": "app/views/tests/update.js.erb",
"chars": 84,
"preview": "$(\".modal\").modal(\"hide\")\n$(window.location.replace(\"<%= test_path(@test.slug) %>\"))"
},
{
"path": "app/views/tests/update_result_label.js.erb",
"chars": 53,
"preview": "$(\".modal\").modal(\"hide\")\n$(window.location.reload())"
},
{
"path": "app/views/user_settings/_modal.html.slim",
"chars": 4385,
"preview": ".account-settings-modal.modal-dialog\n .modal-content\n .modal-header\n button.close type=\"button\" data-dismiss=\"m"
},
{
"path": "app/views/user_settings/edit.js.erb",
"chars": 114,
"preview": "$(\".modal\").html(\"<%= escape_javascript(render 'modal') %>\")\nLadda.bind(\".ladda-button\")\n$(\".modal\").modal(\"show\")"
},
{
"path": "app/views/user_settings/update.js.erb",
"chars": 53,
"preview": "$(\".modal\").modal(\"hide\")\n$(window.location.reload())"
},
{
"path": "bin/bundle",
"chars": 129,
"preview": "#!/usr/bin/env ruby\nENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)\nload Gem.bin_path('bundler', '"
},
{
"path": "bin/rails",
"chars": 145,
"preview": "#!/usr/bin/env ruby\nAPP_PATH = File.expand_path('../../config/application', __FILE__)\nrequire_relative '../config/boot'\n"
},
{
"path": "bin/rake",
"chars": 90,
"preview": "#!/usr/bin/env ruby\nrequire_relative '../config/boot'\nrequire 'rake'\nRake.application.run\n"
},
{
"path": "bin/setup",
"chars": 805,
"preview": "#!/usr/bin/env ruby\nrequire 'pathname'\n\n# path to your application root.\nAPP_ROOT = Pathname.new File.expand_path('../.."
},
{
"path": "circle.yml",
"chars": 105,
"preview": "machine:\n ruby:\n version: 2.3.0\ndatabase:\n pre:\n - cp config/mailer.yml.example config/mailer.yml"
},
{
"path": "config/application.rb",
"chars": 1544,
"preview": "require File.expand_path('../boot', __FILE__)\n\nrequire \"rails\"\n# Pick the frameworks you want:\nrequire \"active_model/rai"
},
{
"path": "config/boot.rb",
"chars": 132,
"preview": "ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)\n\nrequire 'bundler/setup' # Set up gems listed in t"
},
{
"path": "config/database.yml",
"chars": 552,
"preview": "# SQLite version 3.x\n# gem install sqlite3\n#\n# Ensure the SQLite 3 gem is defined in your Gemfile\n# gem 'sqlite3'\n"
},
{
"path": "config/environment.rb",
"chars": 150,
"preview": "# Load the Rails application.\nrequire File.expand_path('../application', __FILE__)\n\n# Initialize the Rails application.\n"
},
{
"path": "config/environments/development.rb",
"chars": 1896,
"preview": "Rails.application.configure do\n # Settings specified here will take precedence over those in config/application.rb.\n\n "
},
{
"path": "config/environments/production.rb",
"chars": 3228,
"preview": "Rails.application.configure do\n # Settings specified here will take precedence over those in config/application.rb.\n\n "
},
{
"path": "config/environments/test.rb",
"chars": 1755,
"preview": "Rails.application.configure do\n # Settings specified here will take precedence over those in config/application.rb.\n\n "
},
{
"path": "config/i18n-js.yml",
"chars": 687,
"preview": "# Split context in several files.\n# By default only one file with all translations is exported and\n# no configuration is"
},
{
"path": "config/initializers/action_mailer.rb",
"chars": 231,
"preview": "unless Chibineko::Application.config.action_mailer.nil?\n if options = YAML.load_file(Rails.root.join(\"config\", \"mailer."
},
{
"path": "config/initializers/assets.rb",
"chars": 486,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Version of your assets, change this if you want to expire"
},
{
"path": "config/initializers/backtrace_silencers.rb",
"chars": 404,
"preview": "# Be sure to restart your server when you modify this file.\n\n# You can add backtrace silencers for libraries that you're"
},
{
"path": "config/initializers/cookies_serializer.rb",
"chars": 129,
"preview": "# Be sure to restart your server when you modify this file.\n\nRails.application.config.action_dispatch.cookies_serializer"
},
{
"path": "config/initializers/devise.rb",
"chars": 13105,
"preview": "# Use this hook to configure devise mailer, warden hooks and so forth.\n# Many of these configuration options can be set "
},
{
"path": "config/initializers/filter_parameter_logging.rb",
"chars": 194,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Configure sensitive parameters which will be filtered fro"
},
{
"path": "config/initializers/inflections.rb",
"chars": 647,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Add new inflection rules using the following format. Infl"
},
{
"path": "config/initializers/mime_types.rb",
"chars": 156,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Add new mime types for use in respond_to blocks:\n# Mime::"
},
{
"path": "config/initializers/session_store.rb",
"chars": 141,
"preview": "# Be sure to restart your server when you modify this file.\n\nRails.application.config.session_store :cookie_store, key: "
},
{
"path": "config/initializers/time_formats.rb",
"chars": 0,
"preview": ""
},
{
"path": "config/initializers/wrap_parameters.rb",
"chars": 517,
"preview": "# Be sure to restart your server when you modify this file.\n\n# This file contains settings for ActionController::ParamsW"
},
{
"path": "config/locales/devise.en.yml",
"chars": 3975,
"preview": "# Additional translations at https://github.com/plataformatec/devise/wiki/I18n\n\nen:\n devise:\n confirmations:\n c"
},
{
"path": "config/locales/devise.ja.yml",
"chars": 2513,
"preview": "# Additional translations at https://github.com/plataformatec/devise/wiki/I18n\n\nja:\n devise:\n confirmations:\n c"
},
{
"path": "config/locales/devise_view.en.yml",
"chars": 459,
"preview": "en:\n devise:\n registrations:\n new:\n sign_up: \"Sign up\"\n not_receive: \"Didn't receive confirmation"
},
{
"path": "config/locales/devise_view.ja.yml",
"chars": 396,
"preview": "ja:\n devise:\n registrations:\n new:\n sign_up: \"ユーザー登録\"\n not_receive: \"登録確認メールが届かない方はこちら\"\n confi"
},
{
"path": "config/locales/en.yml",
"chars": 7976,
"preview": "en:\n language_name: \"English\"\n\n common:\n created_by: \"Created by\"\n updated_at: \"Updated at\"\n updated_on: \"Upd"
},
{
"path": "config/locales/ja.yml",
"chars": 6383,
"preview": "ja:\n language_name: \"日本語\"\n\n common:\n created_by: \"作成者\"\n updated_at: \"更新日時\"\n updated_on: \"更新日\"\n dashboard: "
},
{
"path": "config/locales/js.en.yml",
"chars": 1015,
"preview": "en:\n js:\n team_sidebar:\n edit_members:\n search_user: \"Search user...\"\n add_user: \"Add this user t"
},
{
"path": "config/locales/js.ja.yml",
"chars": 870,
"preview": "ja:\n js:\n team_sidebar:\n edit_members:\n search_user: \"検索中...\"\n add_user: \"ユーザーをチームに追加\"\n no"
},
{
"path": "config/locales/terms.en.yml",
"chars": 22060,
"preview": "en:\n static_pages:\n terms:\n title: \"Terms of Service\"\n body_html: |\n <p>Last modified: January 20, "
},
{
"path": "config/locales/terms.ja.yml",
"chars": 11579,
"preview": "ja:\n static_pages:\n terms:\n title: \"サービス利用規約\"\n body_html: |\n <p>2015年1月20日 制定</p>\n\n <h2>第 1 "
},
{
"path": "config/mailer.yml.example",
"chars": 464,
"preview": "defaults: &defaults\n\ndevelopment:\n default_url_options:\n host: \"localhost\"\n port: \"3000\"\n\ntest:\n default_url_opt"
},
{
"path": "config/routes.rb",
"chars": 1012,
"preview": "Rails.application.routes.draw do\n root 'static_pages#top'\n get 'terms' => 'static_pages#terms'\n get 'dashboard' => 'd"
},
{
"path": "config/secrets.yml",
"chars": 964,
"preview": "# Be sure to restart your server when you modify this file.\n\n# Your secret key is used for verifying the integrity of si"
},
{
"path": "config.ru",
"chars": 153,
"preview": "# This file is used by Rack-based servers to start the application.\n\nrequire ::File.expand_path('../config/environment',"
},
{
"path": "db/migrate/20151224022612_devise_create_users.rb",
"chars": 1346,
"preview": "class DeviseCreateUsers < ActiveRecord::Migration\n def change\n create_table(:users) do |t|\n ## Database authent"
},
{
"path": "db/migrate/20151224030646_create_teams.rb",
"chars": 225,
"preview": "class CreateTeams < ActiveRecord::Migration\n def change\n create_table :teams do |t|\n t.string :name, null: fals"
},
{
"path": "db/migrate/20151225045046_create_projects.rb",
"chars": 316,
"preview": "class CreateProjects < ActiveRecord::Migration\n def change\n create_table :projects do |t|\n t.string :name, null"
},
{
"path": "db/migrate/20151225141534_create_tests.rb",
"chars": 329,
"preview": "class CreateTests < ActiveRecord::Migration\n def change\n create_table :tests do |t|\n t.string :slug, null: fals"
},
{
"path": "db/migrate/20151226051709_create_testcases.rb",
"chars": 309,
"preview": "class CreateTestcases < ActiveRecord::Migration\n def change\n create_table :testcases do |t|\n t.integer :heading"
},
{
"path": "db/migrate/20160103121144_add_column_to_user.rb",
"chars": 195,
"preview": "class AddColumnToUser < ActiveRecord::Migration\n def change\n add_column :users, :username, :string\n add_column :u"
},
{
"path": "db/migrate/20160109162956_create_team_users.rb",
"chars": 331,
"preview": "class CreateTeamUsers < ActiveRecord::Migration\n def change\n create_table :team_users do |t|\n t.integer :team_i"
},
{
"path": "db/migrate/20160319072222_add_created_at_index_to_test.rb",
"chars": 147,
"preview": "class AddCreatedAtIndexToTest < ActiveRecord::Migration\n def change\n add_index :tests, :created_at\n add_index :te"
},
{
"path": "db/schema.rb",
"chars": 3939,
"preview": "# encoding: UTF-8\n# This file is auto-generated from the current state of the database. Instead\n# of editing this file, "
},
{
"path": "db/seeds.rb",
"chars": 97,
"preview": "user = User.create(email: \"test@example.com\", password: \"test\")\nuser.skip_confirmation!\nuser.save"
},
{
"path": "lib/assets/.keep",
"chars": 0,
"preview": ""
},
{
"path": "lib/tasks/.keep",
"chars": 0,
"preview": ""
},
{
"path": "log/.keep",
"chars": 0,
"preview": ""
},
{
"path": "public/404.en.html",
"chars": 639,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>404 | Chibineko</title>\n <meta name=\"viewport\" content=\"width=device-width,initi"
},
{
"path": "public/404.ja.html",
"chars": 603,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>404 | Chibineko</title>\n <meta name=\"viewport\" content=\"width=device-width,initi"
},
{
"path": "public/422.en.html",
"chars": 630,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>422 | Chibineko</title>\n <meta name=\"viewport\" content=\"width=device-width,initi"
},
{
"path": "public/422.ja.html",
"chars": 597,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>422 | Chibineko</title>\n <meta name=\"viewport\" content=\"width=device-width,initi"
},
{
"path": "public/500.en.html",
"chars": 636,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>500 | Chibineko</title>\n <meta name=\"viewport\" content=\"width=device-width,initi"
},
{
"path": "public/500.ja.html",
"chars": 595,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>500 | Chibineko</title>\n <meta name=\"viewport\" content=\"width=device-width,initi"
},
{
"path": "public/error.css",
"chars": 575,
"preview": "body {\n text-align: center;\n padding-top: 60px;\n color: #555;\n}\n\n.dialog {\n display: inline-block;\n text-align: lef"
},
{
"path": "public/javascripts/translations.js",
"chars": 1574,
"preview": "var I18n = I18n || {};\nI18n.translations = {\"en\":{\"js\":{\"team_sidebar\":{\"edit_members\":{\"search_user\":\"Search user...\",\""
},
{
"path": "public/maintenance.html",
"chars": 536,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>503 | Chibineko</title>\n <meta name=\"viewport\" content=\"width=device-width,initi"
},
{
"path": "public/robots.txt",
"chars": 202,
"preview": "# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file\n#\n# To ban all spiders"
},
{
"path": "spec/factories/testcases.rb",
"chars": 55,
"preview": "FactoryGirl.define do\n factory :testcase do\n end\nend\n"
},
{
"path": "spec/factories/tests.rb",
"chars": 98,
"preview": "FactoryGirl.define do\n factory :test do\n sequence(:title) { |n| \"test_title_#{n}\" }\n end\nend\n"
},
{
"path": "spec/models/test_spec.rb",
"chars": 3051,
"preview": "require 'rails_helper'\n\nRSpec.describe Test, type: :model do\n let(:test) { create(:test) }\n let(:labels) {\n resul"
}
]
// ... and 6 more files (download for full content)
About this extraction
This page contains the full source code of the tabbyz/chibineko GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 206 files (229.6 KB), approximately 71.0k tokens, and a symbol index with 130 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.