diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..2d6860cf0 --- /dev/null +++ b/.env.example @@ -0,0 +1,23 @@ +PORT=3000 + +RACK_ENV=development +RAILS_ENV=development + +MAX_THREADS=2 +WEB_CONCURRENCY=2 + +FORCE_SSL=false + +DB_ADAPTER=mysql2 +DB_HOST=mysql +DB_USERNAME=root +DB_PASSWORD=password +DB_NAME=quepid + +REDIS_URL=redis://redis:6379/1 + +QUEPID_GA=UA- +QUEPID_DOMAIN=localhost + +INTERCOM_APP_ID= +INTERCOM_API_KEY= diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 000000000..eded9f22a --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,127 @@ +# How to contribute + +This guide is essential to keeping the contribution process easy and simple for everyone. As the team grows, we need to make sure there are guidelines for what is expected from each contributor. Also, to ensure that the applications we contribute to continue to be maintainable, we need to define what that looks like. + + +## Getting Started + +* Make sure you have a [GitHub account](https://github.com/signup/free) +* Submit a ticket for your issue, assuming one does not already exist. + * Clearly describe the issue including steps to reproduce when it is a bug. + * Use the `ISSUE_TEMPLATE/*` as a guide. +* Clone the repo. + +## Making Changes + +* Create a topic branch from where you want to base your work. + * This is usually the staging branch. + * Only target release branches if you are certain your fix must be on that + branch. + * Use the type of work (feature, bugfix, enhancement) at the beginning of the branch name if applicable (eg. `feature/123-branch-name`). + * Follow the type by the Github ticket number at the beginning of the branch name if applicable (eg. `feature/123-branch-name`). + * Use a short but descriptive name of the branch that matches the ticket title or summary (eg. `feature/123-add-csv-import`). + * Use dashes in the name as a separator. + * To quickly create a topic branch based on staging; `git checkout -b feature/123-add-csv-import staging`. Please avoid working directly on the + `master` or the `staging` branch. +* Make commits of logical units. +* Check for unnecessary whitespace with `git diff --check` before committing. + * Make sure you have setup your editor to trim ending whitespace. + * Make sure you have setup your editor to add an empty line at the end of each file. + * Make sure you have setup your editor to use spaces instead of tabs, and indentations of 2 spaces. +* Run `rubocop` before committing to ensure your changes meet our style guidelines. + * Even though rubocop allows lines of up to 120 characters, try to keep it under 80. + * Set your editor to show a wrap-guide line at 80 characters to help you follow this rule. + * You can disable rubocop rules inline when necessary, but try not to make a habit of it. + * If you strongly disagree with a rubocop rule, discuss it with the team and we can + potentially change the configuration. +* Make sure your commit messages are in the proper format. + +```git +(#123) Make the example in CONTRIBUTING imperative and concrete + +Without this patch applied the example commit message in the CONTRIBUTING +document is not a concrete example. This is a problem because the +contributor is left to imagine what the commit message should look like +based on a description rather than an example. This patch fixes the +problem by making the example concrete and imperative. + +The first line is a real life imperative statement with a ticket number +from our issue tracker. The body describes the behavior without the patch, +why this is a problem, and how the patch fixes the problem when applied. +``` + +* Make sure you have added the necessary tests for your changes. +* Run _all_ the tests to assure nothing else was accidentally broken. + +## Writing Translatable Code + +Rails has i18n baked in, so we should put all user facing strings in translation files. + +When adding user-facing strings to your work, follow these guidelines: +* Use full sentences. Strings built up out of concatenated bits are hard to translate. +* Use scopes to organize strings based on where they are used. + Example: + ```yml + en: + views: + qualified_leads: + index: + header: Qualified Leads + ``` + or + ```yml + en: + mailers: + qualified_leads: + notify_admins: + subject: New Qualified Lead + ``` +* Use a directory structure that mimics the namespacing. +* Use the name of the class (eg. the AR model, or controller) to group strings. +* Use the name of the method or action when applicable. +* Use `success` and `error` under controller actions to differentiate between the happy path and the failure path. +* Use variables when needed to pass dynamic content to the string. + Ex. `t :body, scope: [ :qualified_lead_mailer, :notify_admins ], lead_id: @lead.short_id, name: @name` +* Use pluralization that is baked into Rails i18n for handling situations where the count matters. + +For more info, checkout the [guides](https://guides.rubyonrails.org/i18n.html). + +It is the responsibility of contributors and code reviewers to ensure that all user-facing strings are marked in new PRs before merging. + +## Making Trivial Changes + +### Documentation + +For changes of a trivial nature to comments and documentation, it is not +always necessary to create a new ticket. In this case, it is appropriate to +start the first line of a commit with the type of change (eg. '(doc)' or '(bugfix)') instead of a ticket number. + +```git +(doc) Add documentation commit example to CONTRIBUTING + +There is no example for contributing a documentation commit +to the repository. This is a problem because the contributor +is left to assume how a commit of this nature may appear. + +The first line is a real life imperative statement with '(doc)' in +place of what would have been the ticket number in a +non-documentation related commit. The body describes the nature of +the new documentation or comments added. +``` + +## Submitting Changes + +* Push your changes to a topic branch. +* Submit a pull request to the repository. +* Try to keep PRs small, focused and self-contained. The goal is to have a high velocity of small changes instead of less frequent, large changes. +* Assign another developer as the primary reviewer. They should try to review the PR within one business day time. +* Try to respond to PR feedback within one business day. If a requested change is going to require more time to develop, at least acknowledge the comment and consider applying an "updating per feedback" label to the PR. +* PRs may not be merged to master until they have been approved by at least one other developer. +* Use PR labels to flag special cases, like "not ready for review" or "do not deploy" +* You can mention other developers that might be interested in a comment or description with an `FYI @username` reference. + + +# Additional Resources + +* [General GitHub documentation](https://help.github.com/) +* [GitHub pull request documentation](https://help.github.com/articles/creating-a-pull-request/) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..dd84ea782 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..bbcbbe7d6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..e6d218d97 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,31 @@ + + +## Description + + +## Motivation and Context + + + +## How Has This Been Tested? + + + + +## Screenshots or GIFs (if appropriate): + +## Types of changes + +- [] Bug fix (non-breaking change which fixes an issue) +- [] New feature (non-breaking change which adds functionality) +- [] Breaking change (fix or feature that would cause existing functionality to change) + +## Checklist: + + +- [] My code follows the code style of this project. +- [] My change requires a change to the documentation. +- [] I have updated the documentation accordingly. +- [] I have read the **CONTRIBUTING** document. +- [] I have added tests to cover my changes. +- [] All new and existing tests passed. diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..a89088463 --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +# VIM swp +*.swp + +# Project files +.idea/ + +# Mac +.DS_Store + +# Ignore bundler config. +/.bundle + +# Ignore the default SQLite database. +/db/*.sqlite3 +/db/*.sqlite +/db/*.sqlite3-journal + +# Ignore all logfiles and tempfiles. +/log/* +!/log/.keep +/tmp + +# Ignore vagrant artifacts +.vagrant +vagrant.rb + +# Ignore bower artifacts +/vendor/assets/bower_components + +# Ignore local env file +/.envrc +.env + +# Ignore node artifacts +node_modules +npm-debug.log + +# Rails assets +# Ignore compiled assets +public/assets + +# Test Coverage +coverage/ + +# Docker artifacts +public/srv diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 000000000..904100dba --- /dev/null +++ b/.jshintrc @@ -0,0 +1,42 @@ +{ + "bitwise": true, + "boss": true, + "browser": true, + "camelcase": false, + "curly": true, + "eqeqeq": true, + "eqnull": true, + "esnext": true, + "expr": true, + "immed": true, + "indent": 2, + "latedef": true, + "newcap": true, + "noarg": true, + "node": true, + "quotmark": "single", + "regexp": true, + "smarttabs": true, + "strict": true, + "sub": true, + "trailing": true, + "undef": true, + "unused": true, + "globals": { + "after": false, + "afterEach": false, + "angular": false, + "before": false, + "beforeEach": false, + "browser": false, + "describe": false, + "expect": false, + "inject": false, + "it": false, + "quepidMocks": false, + "spyOn": false, + "testTry": false, + "jQuery": true, + "$": true + } +} \ No newline at end of file diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 000000000..aa8a96ae0 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,78 @@ +AllCops: + Exclude: + - config/puma.rb + - db/**/* + - bin/**/* + - vendor/**/* + - node_modules/**/* + - lib/templates/rails/jbuilder/index.json.jbuilder + - lib/railgun/mailer_decorator.rb + - config/initializers/simple_form.rb + - config/initializers/simple_form_bootstrap.rb + - config/initializers/content_security_policy.rb + +Rails: + Enabled: true + +Rails/Output: + Enabled: false + +Documentation: + Enabled: false + +Layout/AlignHash: + EnforcedColonStyle: table + EnforcedHashRocketStyle: table + +Layout/IndentFirstHashElement: + EnforcedStyle: consistent + +Layout/MultilineMethodCallIndentation: + EnforcedStyle: indented + +Layout/SpaceInsideArrayLiteralBrackets: + EnforcedStyle: space + +Layout/SpaceInsidePercentLiteralDelimiters: + Enabled: false + +Layout/SpaceInsideParens: + Enabled: false + +Metrics/BlockLength: + Exclude: + - test/**/* + +Metrics/ClassLength: + Exclude: + - test/**/* + +Metrics/AbcSize: + Max: 30 + +Metrics/LineLength: + Max: 120 + +Metrics/MethodLength: + Max: 15 + +Metrics/CyclomaticComplexity: + Max: 8 + +Metrics/PerceivedComplexity: + Max: 8 + +Style/Alias: + EnforcedStyle: prefer_alias_method + +Style/Lambda: + Enabled: false + +Style/MethodDefParentheses: + EnforcedStyle: require_no_parentheses_except_multiline + +Style/TrailingCommaInHashLiteral: + EnforcedStyleForMultiline: comma + +Style/YodaCondition: + EnforcedStyle: require_for_equality_operators_only diff --git a/.ruby-version b/.ruby-version new file mode 100755 index 000000000..0cadbc1e3 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.5.5 diff --git a/.ssl/localhost.crt b/.ssl/localhost.crt new file mode 100644 index 000000000..e4dd51691 --- /dev/null +++ b/.ssl/localhost.crt @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIJAIqjUwOvKKfXMA0GCSqGSIb3DQEBBQUAMIGkMQswCQYD +VQQGEwJVUzERMA8GA1UECAwIVmlyZ2luaWExGDAWBgNVBAcMD0NoYXJsb3R0ZXN2 +aWxsZTEfMB0GA1UECgwWT3BlblNvdXJjZSBDb25uZWN0aW9uczEPMA0GA1UECwwG +UXVlcGlkMRYwFAYDVQQDDA1sb2NhbGhvc3Quc3NsMR4wHAYJKoZIhvcNAQkBFg9x +dWVwaWRAbzE5cy5jb20wHhcNMTYwMTI1MTQwNDAyWhcNMTcwMTI0MTQwNDAyWjCB +pDELMAkGA1UEBhMCVVMxETAPBgNVBAgMCFZpcmdpbmlhMRgwFgYDVQQHDA9DaGFy +bG90dGVzdmlsbGUxHzAdBgNVBAoMFk9wZW5Tb3VyY2UgQ29ubmVjdGlvbnMxDzAN +BgNVBAsMBlF1ZXBpZDEWMBQGA1UEAwwNbG9jYWxob3N0LnNzbDEeMBwGCSqGSIb3 +DQEJARYPcXVlcGlkQG8xOXMuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA6v0KMXTDvLbEQB8xXj6qosOkT85GpmFx7tqJFBswLhLf758UeIEYF37u +doxZXDFZmdv3zm32TZsmj2CKL+ES8W2llATpl34vvQym5SZdp7/lia/MAevRn5rJ +15/Sl8TzpAWkk0a9jekUURXbu6Bxvufn1VPQz2HHK4FDRGj753wCYqxM5tNMP7uE +IbsLzyV2vEnYKG7idEc56RyxI4nHR1dCN4R+ruDyy+F8TG5uvQNWJoDsxBV2itFG +0imTcO289wtRY5V+kKSC4LO47UoDDMz6rEX7f+RW1ZCxTHGI5RuyIBqzNOX8DgMm +Kr27D0cLU14yOD//cJeSpL7YnvjqtwIDAQABo1AwTjAdBgNVHQ4EFgQUHV4rc0sO +OL9ogT4nAL4a4mJ80a8wHwYDVR0jBBgwFoAUHV4rc0sOOL9ogT4nAL4a4mJ80a8w +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEACrrMclJ57Fj3Ycs4d8Rd ++fSBtXh2QU76/JRZXJdZYh6NxDCFyCHRSuE8H5Cmrs3P5TtRH7fxzEnIR3bQi1yv +nYWjlxYkpmQci2IeFGyeSJeV8r5ljgNtqCs52flsRVASILdle6giyl0SOXPHjp3L +2CLYEeNrDijQtr0OyPFcdK7yAcXefvkLI1prfm5IASCgiu5yo4TKzN8rsFUnpQWq +OVQou4qIaf/i5Y1CLeIACmx7tb1HsJR3Z1b9aJ8ZvWKaDZDsHsvKMsSUg2Yb6NSk +jTJ+6UdiKpDSpkZuwVyj07GA5XxmsBrMHR27Ha8NqYdhH2+QIqS+wNyXHkXvNZgx +lQ== +-----END CERTIFICATE----- diff --git a/.ssl/localhost.key b/.ssl/localhost.key new file mode 100644 index 000000000..9141bb8f8 --- /dev/null +++ b/.ssl/localhost.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDq/QoxdMO8tsRA +HzFePqqiw6RPzkamYXHu2okUGzAuEt/vnxR4gRgXfu52jFlcMVmZ2/fObfZNmyaP +YIov4RLxbaWUBOmXfi+9DKblJl2nv+WJr8wB69GfmsnXn9KXxPOkBaSTRr2N6RRR +Fdu7oHG+5+fVU9DPYccrgUNEaPvnfAJirEzm00w/u4QhuwvPJXa8SdgobuJ0Rznp +HLEjicdHV0I3hH6u4PLL4XxMbm69A1YmgOzEFXaK0UbSKZNw7bz3C1FjlX6QpILg +s7jtSgMMzPqsRft/5FbVkLFMcYjlG7IgGrM05fwOAyYqvbsPRwtTXjI4P/9wl5Kk +vtie+Oq3AgMBAAECggEADdVLjlHDXA6eSvALJfMmdGJz/8ay3gSKgncW7roTAgNW +b3K778QZuPhd7Vihwg2dqrMKSXqrrzHc+T/DosHrLY842hfX8HUbNlPSV1cE2GUx +jANvTQWm13BzRWBBM3ICrbsvTwQxEHOSIJvazZbKW2SnfyVp+2tUIDmBzjsn6R6E +28lCbPwNrsevK5HoInupFL7Rhn167tdU5HJCazDwQhFb07luB7WnbX2Ray3M48cD +zsZSHs5ktnAu+4PozsvtNYha8Orc+ddnjtRDMZEq0vWrCDxCjPfvDEE5HUwxdhyF +IMT0wv0upOATucY2zyhTrmPq8MQiYz+hmY6dT0Vm0QKBgQD5fC8T42kRI4ZN/E2S +VzGaRsu8wpK/c9qVEptaEtZ0VrA4fYpvHxcyHyeNkoYckZ1vV1DLefAP869KX/E2 +v/sRnhsBT5T3uE44+rnGI1Bb55otpw6HQQ3vn2s/D96AXM+BxczjZ17eQ4hfkd72 +1sicblif0a5O44gM7dzxlu7WBQKBgQDxH/H+mqyK0HjDzHCL47pLHPsaYc/VNiem +1+N9MJgFoqTJ9AVbh5S5sqHZ+UM5P3Gbk3WcgOv3/JjvD/RkeW0HWil63ALKNzNK +8cyxPazre7GKZ944T6jh0v40n8FukTDEo2wZ2/8+kRm5VfzabNblW7E2QPDEXa50 +QBd11he+iwKBgHMpq+GWW+2ZZGmjSXt/3FnGzE0509ukcwXVLPkLMQtK6NVqvfhF +dcOhNfTX6ihN30qCF72VcActCYFfgE0xmYesX/Le9XjUDuemdRLNQk7qPfVM5Bvz +H6e5Axx9CsxeCztwPv/Ju7UFn3HeN/nhc4EiPq6nb7ritO6i7hZnAaCxAoGAMiqG +S4VcrojPB1WKeOBJSwVdjNCaz+4zc7fo4YvxpQKArG+ziaZ8n+H1YIdGoCt99HNK +feQos/B+1QYJv7mvoF720FPj1LSFXGtQPfPp/RhACN6xUh/osAsYzlQKh3l3nwGt +JPgrc5X2tyOXts38K73W8cWzEfe3qwIGn4KKcB8CgYEAqUayhZo2aO+NSPdQ8PXW +OOk85xU/N5v9f5AmPna/wHbmsnaracj23VpbGfm8BR7EUABjhemRTtOQEyIo2U1S +Ck91rwfx5r1wEanFzgoT6GPDpsTa9GQBV+ONhCSWQyiCV04A70Jqt2Oh80I8bzEo +iA1mTwmvPWGsDbG2v3w+lN4= +-----END PRIVATE KEY----- diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..ad84e0529 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,48 @@ +# Changelog + +## 6.0.0 +* Removes everything related to payments, and makes Quepid "free" +* Adds support for using a CORS proxy for Solr instances that are not configured to allow connections from Quepid +* Replaces use of Vagrant in development in favor of Docker +* Adds support for GDPR +* Adds support for deploying Quepid on Heroku +* Upgrades Ruby version +* Upgrades Angular from 1.4.x to 1.7.x +* A bunch of bug fixes + +## 5.0.2 +* bugfix-888 Fixes #886: Locks version number for CSV module. + +## 5.0.1 +* bugfix: ES5 displaying attributes - fields are not automatically stored so `stored_fields` will not return anything, instead get the data from the `_source` field + +## 5.0.0 +* feature: q-score - Added graph for score history +* feature: annotations - User can now take a snapshot of the score with an annotation to describe that point in time +* bugfix-879-880-heatmap-safari Fixes heatmap in Safari + +## 4.2.0 +* add support for ES 5+ with `stored_fields` vs `fields` + +## 4.1.1 +* bugfix: Prevent re-escaping % when it's part of an escape char + +## 4.1.0 (7 months) + +* bugfix-873-change-try-name Fixes renaming try and reloading name in list +* bugfix-872-duplicate-try Fixes #872: Duplicating a try +* bugfix-852-redraw-results-with-snapshot-open Fixes updating results in open query while comparing with a snapshot +* bugfix-848-close-modal-after-deleting-try Closes modal after deleting try +* enhancement-862-document-qa-workflow Adding documentation for QA flow +* feature-863-explain-disabled-features-for-trial-user Enable popups that explain why trial user cannot perform action +* enhancement-document-magic-variables Adds documentation for Magic Variables +* bugfix-844-add-non-existing-user-to-enterprise Fixes feedback when adding non existent user to enterprise +* bugfix-857-case-insensitive-emails Fixes logging in with emails (making them case insensitive) +* bugfix-845-add-team-member Fixes feedback when adding a team member +* bugfix-843-user-autocomplete Removing entire list of users from autocomplete when adding team member +* feature-use-n-docs-in-scoring Allow users to set how many results to display by default instead of the default 10 results +* feature-company-name-in-profile Adds ability to specify company name in user profile +* feature-120-clone-case Adds ability to clone a case +* bug-796-mass-import-ratings Fixes bug in mass import of ratings +* bugfix-767-viewing-snapshots Fixes bug while views snapshots +* bugfix-big-snapshot Fixes bug while viewing large snapshots diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..fac77dd88 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at quepid_admin@opensourceconnections.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/DEPLOY.md b/DEPLOY.md new file mode 100644 index 000000000..85665d358 --- /dev/null +++ b/DEPLOY.md @@ -0,0 +1,33 @@ +# Deployment Instructions +To get started you need Docker images for the application. Is is possible to build your own images using the latest code, or fetch prebuilt images from DockerHub. Both methods are outlined below. + +## Building Your Own Image +To prepare your own images: run `bin/setup_docker.sh`. This script will: + +- Use docker-compose to fetch and build all images required for the application +- Setup the database for Quepid + +This process can take upwards of 20 minutes + +## Using Prebuilt Images +To utilize prebuilt images from docker.io run `bin/setup_docker.sh nobuild`. + +## Setup test users +To create an admin user and other test users, run the following script: + +`bin/docker r bin/rake db:seed:test` + +__Note:__ This is currently the only way to setup an Admin user. You can signup within the app to make new users. + +## Running the Application +After you've run `setup_docker.sh` you can launch the application with the following commands: + +- Start the containers: `bin/docker start` +- Run the App server within the container: `bin/docker daemon` + +__Note:__ If you're interested in seeing request logs, `bin/docker server` will run everything in the foreground. + +## Done +That's it! If you run into issues don't hesitate to reach out. + +[Quepid Slack](http://www.opensourceconnections.com/slack) diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 000000000..bdefbbbaa --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,47 @@ +FROM ruby:2.5.5 + +MAINTAINER OpenSource Connections + +# Must have packages +RUN apt-get update -qq && apt-get install -y vim curl git tmux + +# Install Node +RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - +RUN curl -sL https://deb.nodesource.com/setup_8.x | bash +RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list + +RUN apt-get install -y nodejs +RUN apt-get update && apt-get install -y yarn + +# Install PhantomJS +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + ca-certificates \ + bzip2 \ + libfontconfig \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + curl \ + && mkdir /tmp/phantomjs \ + && curl -L \ + https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2 \ + | tar -xj --strip-components=1 -C /tmp/phantomjs \ + && cd /tmp/phantomjs \ + && mv bin/phantomjs /usr/local/bin \ + && cd \ + && apt-get clean \ + && rm -rf /tmp/* /var/lib/apt/lists/* + +# Install Heroku CLI +RUN curl https://cli-assets.heroku.com/install-ubuntu.sh | sh + +# Clean environment +RUN apt-get clean all + +COPY . /srv/app +WORKDIR /srv/app + +RUN bundle install diff --git a/Gemfile b/Gemfile new file mode 100755 index 000000000..0f4f0c23e --- /dev/null +++ b/Gemfile @@ -0,0 +1,98 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' + +git_source(:github) do |repo_name| + repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?('/') + "https://github.com/#{repo_name}.git" +end + +ruby '2.5.5' + +gem 'ace-rails-ap' +gem 'activerecord-import', '>= 0.13.0' +gem 'activerecord_any_of' +gem 'acts_as_list', github: 'swanandp/acts_as_list' +gem 'angular-rails-templates', '>= 1.0.0.beta' +gem 'bcrypt', '~> 3.1.7' +gem 'bootstrap-sass', '~> 3.3.5' +gem 'coffee-rails', '~> 4.1.0' +gem 'colorize', require: false +gem 'cookies_eu' +gem 'devise' +gem 'font-awesome-sass', '>= 4.4.0' +gem 'gabba' +gem 'intercom' +gem 'intercom-rails' +gem 'jbuilder', '~> 2.0' +gem 'jquery-rails' +gem 'jquery-ui-rails' +gem 'mysql2' +gem 'newrelic_rpm' +gem 'paranoia', '~> 2.0' +gem 'postmark-rails', '~> 0.10.0' +gem 'puma', '~> 3.7' +gem 'puma_worker_killer' +gem 'pundit' +gem 'rails', '~> 4.2', '>= 4.2.5.1' +gem 'responders' +gem 'rsolr', require: false +gem 'sass-rails', '~> 5.0' +gem 'sdoc', '~> 0.4.0', group: :doc +gem 'sidekiq' +gem 'sidetiq' +gem 'sinatra', require: false +gem 'slim' +gem 'uglifier', '>= 1.3.0' + +source 'https://rails-assets.org' do + gem 'rails-assets-angular' + gem 'rails-assets-angular-cache' + gem 'rails-assets-cal-heatmap' + gem 'rails-assets-d3', '~> 3.5.5' +end + +group :development, :test do + gem 'annotate' + gem 'bullet' + gem 'byebug' + gem 'dotenv-rails' + gem 'flamegraph' + gem 'foreman' + gem 'guard' + gem 'guard-minitest' + gem 'memory_profiler' + gem 'rack-mini-profiler' + gem 'spring', '1.6.4' + gem 'stackprof' + gem 'thin' +end + +group :development do + gem 'letter_opener' + gem 'rubocop', require: false + gem 'web-console', '~> 3.0' +end + +group :test do + gem 'database_cleaner' + gem 'jasmine' + gem 'm', '~> 1.5.0' + gem 'minitest-reporters', '>= 0.5.0' + gem 'mocha' + gem 'simplecov', require: false + gem 'timecop' + gem 'webmock' + + source 'https://rails-assets.org' do + gem 'rails-assets-angular-mocks' + end +end + +group :production, :staging do + gem 'rails_12factor' +end + +group :container do + gem 'sqlite3' +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 000000000..38643a272 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,457 @@ +GIT + remote: https://github.com/swanandp/acts_as_list.git + revision: 248bf23161de8c0fbc1ca05b3b7f8ba59a12f79b + specs: + acts_as_list (0.9.17) + activerecord (>= 3.0) + +GEM + remote: https://rubygems.org/ + remote: https://rails-assets.org/ + specs: + ace-rails-ap (4.1.5) + actionmailer (4.2.11) + actionpack (= 4.2.11) + actionview (= 4.2.11) + activejob (= 4.2.11) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 1.0, >= 1.0.5) + actionpack (4.2.11) + actionview (= 4.2.11) + activesupport (= 4.2.11) + rack (~> 1.6) + rack-test (~> 0.6.2) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (4.2.11) + activesupport (= 4.2.11) + builder (~> 3.1) + erubis (~> 2.7.0) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (4.2.11) + activesupport (= 4.2.11) + globalid (>= 0.3.0) + activemodel (4.2.11) + activesupport (= 4.2.11) + builder (~> 3.1) + activerecord (4.2.11) + activemodel (= 4.2.11) + activesupport (= 4.2.11) + arel (~> 6.0) + activerecord-import (1.0.1) + activerecord (>= 3.2) + activerecord_any_of (1.4) + activerecord (>= 3.2.13, < 5) + activesupport (4.2.11) + i18n (~> 0.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + addressable (2.6.0) + public_suffix (>= 2.0.2, < 4.0) + angular-rails-templates (1.0.2) + railties (>= 4.2, < 6) + sprockets (>= 3.0, < 5) + tilt + annotate (2.7.4) + activerecord (>= 3.2, < 6.0) + rake (>= 10.4, < 13.0) + ansi (1.5.0) + arel (6.0.4) + ast (2.4.0) + autoprefixer-rails (9.4.9) + execjs + bcrypt (3.1.12) + bootstrap-sass (3.3.7) + autoprefixer-rails (>= 5.2.1) + sass (>= 3.3.4) + builder (3.2.3) + bullet (5.8.0) + activesupport (>= 3.0.0) + uniform_notifier (~> 1.11) + byebug (10.0.2) + celluloid (0.17.4) + celluloid-essentials + celluloid-extras + celluloid-fsm + celluloid-pool + celluloid-supervision + timers (>= 4.1.1) + celluloid-essentials (0.20.5) + timers (>= 4.1.1) + celluloid-extras (0.20.5) + timers (>= 4.1.1) + celluloid-fsm (0.20.5) + timers (>= 4.1.1) + celluloid-pool (0.20.5) + timers (>= 4.1.1) + celluloid-supervision (0.20.6) + timers (>= 4.1.1) + coderay (1.1.2) + coffee-rails (4.1.1) + coffee-script (>= 2.2.0) + railties (>= 4.0.0, < 5.1.x) + coffee-script (2.4.1) + coffee-script-source + execjs + coffee-script-source (1.12.2) + colorize (0.8.1) + concurrent-ruby (1.1.4) + connection_pool (2.2.2) + cookies_eu (1.7.5) + js_cookie_rails (~> 2.2.0) + crack (0.4.3) + safe_yaml (~> 1.0.0) + crass (1.0.4) + daemons (1.3.1) + database_cleaner (1.7.0) + debug_inspector (0.0.3) + devise (4.6.1) + bcrypt (~> 3.0) + orm_adapter (~> 0.1) + railties (>= 4.1.0, < 6.0) + responders + warden (~> 1.2.3) + docile (1.3.1) + dotenv (2.7.1) + dotenv-rails (2.7.1) + dotenv (= 2.7.1) + railties (>= 3.2, < 6.1) + erubis (2.7.0) + eventmachine (1.2.7) + execjs (2.7.0) + faraday (0.15.4) + multipart-post (>= 1.2, < 3) + ffi (1.9.25) + flamegraph (0.9.5) + font-awesome-sass (5.6.1) + sassc (>= 1.11) + foreman (0.85.0) + thor (~> 0.19.1) + formatador (0.2.5) + gabba (1.0.1) + get_process_mem (0.2.3) + globalid (0.4.2) + activesupport (>= 4.2.0) + guard (2.15.0) + formatador (>= 0.2.4) + listen (>= 2.7, < 4.0) + lumberjack (>= 1.0.12, < 2.0) + nenv (~> 0.1) + notiffany (~> 0.0) + pry (>= 0.9.12) + shellany (~> 0.0) + thor (>= 0.18.1) + guard-compat (1.2.1) + guard-minitest (2.4.6) + guard-compat (~> 1.2) + minitest (>= 3.0) + hashdiff (0.3.8) + i18n (0.9.5) + concurrent-ruby (~> 1.0) + ice_cube (0.14.0) + intercom (3.7.3) + intercom-rails (0.4.0) + activesupport (> 3.0) + jaro_winkler (1.5.2) + jasmine (2.99.0) + jasmine-core (>= 2.99.0, < 3.0.0) + phantomjs + rack (>= 1.2.1) + rake + jasmine-core (2.99.2) + jbuilder (2.8.0) + activesupport (>= 4.2.0) + multi_json (>= 1.2) + jquery-rails (4.3.3) + rails-dom-testing (>= 1, < 3) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) + jquery-ui-rails (6.0.1) + railties (>= 3.2.16) + js_cookie_rails (2.2.0) + railties (>= 3.1) + json (1.8.6) + launchy (2.4.3) + addressable (~> 2.3) + letter_opener (1.7.0) + launchy (~> 2.2) + listen (3.1.5) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + ruby_dep (~> 1.2) + loofah (2.2.3) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + lumberjack (1.0.13) + m (1.5.1) + method_source (>= 0.6.7) + rake (>= 0.9.2.2) + mail (2.7.1) + mini_mime (>= 0.1.1) + memory_profiler (0.9.12) + metaclass (0.0.4) + method_source (0.9.2) + mini_mime (1.0.1) + mini_portile2 (2.4.0) + minitest (5.11.3) + minitest-reporters (1.3.6) + ansi + builder + minitest (>= 5.0) + ruby-progressbar + mocha (1.8.0) + metaclass (~> 0.0.1) + multi_json (1.13.1) + multipart-post (2.0.0) + mysql2 (0.5.2) + nenv (0.3.0) + newrelic_rpm (6.1.0.352) + nokogiri (1.9.1) + mini_portile2 (~> 2.4.0) + notiffany (0.1.1) + nenv (~> 0.1) + shellany (~> 0.0) + orm_adapter (0.5.0) + parallel (1.17.0) + paranoia (2.4.1) + activerecord (>= 4.0, < 5.3) + parser (2.6.3.0) + ast (~> 2.4.0) + phantomjs (2.1.1.0) + postmark (1.5.0) + json + rake + postmark-rails (0.10.0) + actionmailer (>= 3.0.0) + postmark (~> 1.5.0) + pry (0.12.2) + coderay (~> 1.1.0) + method_source (~> 0.9.0) + public_suffix (3.0.3) + puma (3.12.0) + puma_worker_killer (0.1.0) + get_process_mem (~> 0.2) + puma (>= 2.7, < 4) + pundit (2.0.1) + activesupport (>= 3.0.0) + rack (1.6.11) + rack-mini-profiler (1.0.0) + rack (>= 1.2.0) + rack-protection (1.5.5) + rack + rack-test (0.6.3) + rack (>= 1.0) + rails (4.2.11) + actionmailer (= 4.2.11) + actionpack (= 4.2.11) + actionview (= 4.2.11) + activejob (= 4.2.11) + activemodel (= 4.2.11) + activerecord (= 4.2.11) + activesupport (= 4.2.11) + bundler (>= 1.3.0, < 2.0) + railties (= 4.2.11) + sprockets-rails + rails-assets-angular (1.7.5) + rails-assets-angular-cache (4.6.0) + rails-assets-angular (>= 1) + rails-assets-angular-mocks (1.7.5) + rails-assets-angular (= 1.7.5) + rails-assets-cal-heatmap (3.6.2) + rails-assets-d3 (>= 3.0.6, < 4.0.0) + rails-assets-d3 (3.5.17) + rails-deprecated_sanitizer (1.0.3) + activesupport (>= 4.2.0.alpha) + rails-dom-testing (1.0.9) + activesupport (>= 4.2.0, < 5.0) + nokogiri (~> 1.6) + rails-deprecated_sanitizer (>= 1.0.1) + rails-html-sanitizer (1.0.4) + loofah (~> 2.2, >= 2.2.2) + rails_12factor (0.0.3) + rails_serve_static_assets + rails_stdout_logging + rails_serve_static_assets (0.0.5) + rails_stdout_logging (0.0.5) + railties (4.2.11) + actionpack (= 4.2.11) + activesupport (= 4.2.11) + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + rainbow (3.0.0) + rake (12.3.2) + rb-fsevent (0.10.3) + rb-inotify (0.10.0) + ffi (~> 1.0) + rdoc (4.3.0) + redis (4.1.0) + responders (2.4.1) + actionpack (>= 4.2.0, < 6.0) + railties (>= 4.2.0, < 6.0) + rsolr (2.2.1) + builder (>= 2.1.2) + faraday (>= 0.9.0) + rubocop (0.70.0) + jaro_winkler (~> 1.5.1) + parallel (~> 1.10) + parser (>= 2.6) + rainbow (>= 2.2.2, < 4.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 1.7) + ruby-progressbar (1.10.0) + ruby_dep (1.5.0) + safe_yaml (1.0.5) + sass (3.7.3) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sass-rails (5.0.7) + railties (>= 4.0.0, < 6) + sass (~> 3.1) + sprockets (>= 2.8, < 4.0) + sprockets-rails (>= 2.0, < 4.0) + tilt (>= 1.1, < 3) + sassc (1.12.1) + ffi (~> 1.9.6) + sass (>= 3.3.0) + sdoc (0.4.2) + json (~> 1.7, >= 1.7.7) + rdoc (~> 4.0) + shellany (0.0.1) + sidekiq (5.2.5) + connection_pool (~> 2.2, >= 2.2.2) + rack (>= 1.5.0) + rack-protection (>= 1.5.0) + redis (>= 3.3.5, < 5) + sidetiq (0.7.2) + celluloid (>= 0.17.3) + ice_cube (~> 0.14.0) + sidekiq (>= 4.1.0) + simplecov (0.16.1) + docile (~> 1.1) + json (>= 1.8, < 3) + simplecov-html (~> 0.10.0) + simplecov-html (0.10.2) + sinatra (1.4.8) + rack (~> 1.5) + rack-protection (~> 1.4) + tilt (>= 1.3, < 3) + slim (4.0.1) + temple (>= 0.7.6, < 0.9) + tilt (>= 2.0.6, < 2.1) + spring (1.6.4) + sprockets (3.7.2) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.2.1) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + sqlite3 (1.4.0) + stackprof (0.2.12) + temple (0.8.0) + thin (1.7.2) + daemons (~> 1.0, >= 1.0.9) + eventmachine (~> 1.0, >= 1.0.4) + rack (>= 1, < 3) + thor (0.19.4) + thread_safe (0.3.6) + tilt (2.0.9) + timecop (0.9.1) + timers (4.3.0) + tzinfo (1.2.5) + thread_safe (~> 0.1) + uglifier (4.1.20) + execjs (>= 0.3.0, < 3) + unicode-display_width (1.6.0) + uniform_notifier (1.12.0) + warden (1.2.7) + rack (>= 1.0) + web-console (3.3.0) + activemodel (>= 4.2) + debug_inspector + railties (>= 4.2) + webmock (3.5.1) + addressable (>= 2.3.6) + crack (>= 0.3.2) + hashdiff + +PLATFORMS + ruby + +DEPENDENCIES + ace-rails-ap + activerecord-import (>= 0.13.0) + activerecord_any_of + acts_as_list! + angular-rails-templates (>= 1.0.0.beta) + annotate + bcrypt (~> 3.1.7) + bootstrap-sass (~> 3.3.5) + bullet + byebug + coffee-rails (~> 4.1.0) + colorize + cookies_eu + database_cleaner + devise + dotenv-rails + flamegraph + font-awesome-sass (>= 4.4.0) + foreman + gabba + guard + guard-minitest + intercom + intercom-rails + jasmine + jbuilder (~> 2.0) + jquery-rails + jquery-ui-rails + letter_opener + m (~> 1.5.0) + memory_profiler + minitest-reporters (>= 0.5.0) + mocha + mysql2 + newrelic_rpm + paranoia (~> 2.0) + postmark-rails (~> 0.10.0) + puma (~> 3.7) + puma_worker_killer + pundit + rack-mini-profiler + rails (~> 4.2, >= 4.2.5.1) + rails-assets-angular! + rails-assets-angular-cache! + rails-assets-angular-mocks! + rails-assets-cal-heatmap! + rails-assets-d3 (~> 3.5.5)! + rails_12factor + responders + rsolr + rubocop + sass-rails (~> 5.0) + sdoc (~> 0.4.0) + sidekiq + sidetiq + simplecov + sinatra + slim + spring (= 1.6.4) + sqlite3 + stackprof + thin + timecop + uglifier (>= 1.3.0) + web-console (~> 3.0) + webmock + +RUBY VERSION + ruby 2.5.5p157 + +BUNDLED WITH + 1.17.3 diff --git a/Guardfile b/Guardfile new file mode 100644 index 000000000..da48aac99 --- /dev/null +++ b/Guardfile @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +# A sample Guardfile +# More info at https://github.com/guard/guard#readme + +guard :minitest do + # with Minitest::Unit + # watch(%r{^test/(.*)\/?test_(.*)\.rb$}) + # watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}test_#{m[2]}.rb" } + # watch(%r{^test/test_helper\.rb$}) { 'test' } + + # with Minitest::Spec + # watch(%r{^spec/(.*)_spec\.rb$}) + # watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } + # watch(%r{^spec/spec_helper\.rb$}) { 'spec' } + + # Rails 4 + watch(%r{^app/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" } + watch(%r{^app/controllers/application_controller\.rb$}) { 'test/controllers' } + watch(%r{^app/controllers/(.+)_controller\.rb$}) { |m| "test/integration/#{m[1]}_test.rb" } + watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" } + watch(%r{^lib/(.+)\.rb$}) { |m| "test/lib/#{m[1]}_test.rb" } + watch(%r{^test/.+_test\.rb$}) + watch(%r{^test/test_helper\.rb$}) { 'test' } + + # Rails < 4 + # watch(%r{^app/controllers/(.*)\.rb$}) { |m| "test/functional/#{m[1]}_test.rb" } + # watch(%r{^app/helpers/(.*)\.rb$}) { |m| "test/helpers/#{m[1]}_test.rb" } + # watch(%r{^app/models/(.*)\.rb$}) { |m| "test/unit/#{m[1]}_test.rb" } +end diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + 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 [yyyy] [name of copyright owner] + + 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. diff --git a/Procfile b/Procfile new file mode 100644 index 000000000..9a3f5908e --- /dev/null +++ b/Procfile @@ -0,0 +1,2 @@ +web: bundle exec puma -C config/puma.rb +worker: bundle exec sidekiq -e production -C config/sidekiq.yml -q default diff --git a/Procfile.dev b/Procfile.dev new file mode 100644 index 000000000..40e61e988 --- /dev/null +++ b/Procfile.dev @@ -0,0 +1,4 @@ +web: bundle exec puma -C config/puma.rb +worker: bundle exec sidekiq -e development -C config/sidekiq.yml -q default + +# web: bundle exec thin start -p 3001 --ssl --ssl-key-file .ssl/localhost.key --ssl-cert-file .ssl/localhost.crt diff --git a/README.md b/README.md new file mode 100644 index 000000000..7cd99a422 --- /dev/null +++ b/README.md @@ -0,0 +1,387 @@ +# Table of Contents + + + +- [Development Setup](#development-setup) + - [I. System Dependencies](#i-system-dependencies) + - [Using Docker Compose](#using-docker-compose) + - [1. Prerequisites](#1-prerequisites) + - [2. Setup your environment](#2-setup-your-environment) + - [3. Running the app](#3-running-the-app) + - [II. Development Log](#ii-development-log) + - [III. Run Tests](#iii-run-tests) + - [BEFORE RUNNING TESTS](#before-running-tests) + - [Minitest](#minitest) + - [JS Lint](#js-lint) + - [Karma](#karma) + - [All Tests](#all-tests) + - [Performance Testing](#performance-testing) + - [IV. Debugging](#iv-debugging) + - [Debugging Ruby](#debugging-ruby) + - [Debugging JS](#debugging-js) + - [Convenience Scripts](#convenience-scripts) + - [Rake](#rake) + - [Thor](#thor) +- [Elasticsearch](#elasticsearch) +- [Dev Errata](#dev-errata) + - [I'd like to use a new Node module](#id-like-to-use-a-new-node-module) + - [I'd like to test SSL](#id-like-to-test-ssl) +- [QA](#qa) + - [Seed Data](#seed-data) +- [Data Map](#data-map) +- [App Structure](#app-structure) +- [Legal Pages](#legal-pages) + + + +# Development Setup + +## I. System Dependencies + +### Using Docker Compose + +Provisioning from an already built machine takes approximately 3 - 4 minutes. Provisioning from scratch takes approximately 20 minutes. + +#### 1. Prerequisites + +Make sure you have installed Docker. Go here https://www.docker.com/community-edition#/download for installation instructions. And the Docker app is launched. + +To install using brew follow these steps: + +``` +brew cask install docker +brew cask install docker-toolbox +``` + +**NOTE:** you may get a warning about trusting Oracle on the first try. Open System Preferences > Security & Privacy, click the Allow Oracle button, and then try again to install docker-toolbox + +#### 2. Setup your environment + +Run the setup script: + +``` +bin/setup_docker +``` + +potentially seed the db to have something to work with (the output will print out credentials you can use for test users): + +``` +bin/docker r bin/rake db:seed:test +``` + +#### 3. Running the app + +We've created a helper script to run and manage the app through docker that wraps around the `docker-compose` command. +You can still use `docker-compose` directly, but for the basic stuff you can use the following: + +* Building the image: `bin/docker build` or `bin/docker b` +* Start the vm: `bin/docker start` or `bin/docker t` +* Stop the vm: `bin/docker stop` or `bin/docker p` +* Destroy the image: `bin/docker destroy` or `bin/docker d` +* Start the app: `bin/docker server` or `bin/docker s` +* Connect to the app container with bash: `bin/docker bash` or `bin/docker c` +* Run any command: `bin/docker run [COMMAND]` or `bin/docker r [COMMAND]` +* Run unit tests: `bin/docker r bin/rake test:quepid` + +## II. Development Log + +While running the app under foreman, you'll only see a request log, for more detailed logging run the following: + +``` +tail -f -n 200 log/development.log +``` + +or + +``` +bin/docker run tail -f -n 200 log/development.log +``` + +**Note:** To clear the logs to avoid them getting too big run: `cat /dev/null > log/development.log` + +## III. Run Tests + +### BEFORE RUNNING TESTS + +If you aren't using Docker, then create test database... + +``` +rake db:create RAILS_ENV=test +``` + +There are three types of tests that you can run: + +### Minitest + +These tests run the tests from the Rails side (mainly API controllers, and models): + +``` +bin/rake test +``` + +### JS Lint + +To check the JS syntax: + +``` +bin/rake test:jshint +``` + +### Karma + +Runs tests for the Angular side. There are two modes for the karma tests: + +* Single run: `bin/rake karma:run` +* Continuous/watched run: `bin/rake karma:start` + +**Note:** The karma tests require the assets to be precompiled, which adds a significant amount of time to the test run. If you are only making changes to the test/spec files, then it is recommended you run the tests in watch mode (`bin/rake karma:start`). The caveat is that any time you make a change to the app files, you will have to restart the process (or use the single run mode). + +### All Tests + +If you want to run all of the tests in one go (before you commit and push for example), just run the special rake task: + +``` +bin/rake test:quepid +``` + +### Performance Testing + +If you want to create a LOT of queries for a user for testing, then run + +``` +bin/docker r bin/rake db:seed:large +``` + +You will have two users, `quepid+100sOfQueries@o19s.com` and `quepid+1000sOfQueries@o19s.com` to test with. + +## IV. Debugging + +### Debugging Ruby + +Debugging ruby usually depends on the situation, the simplest way is to print out the object to the STDOUT: + +```ruby +puts object # Prints out the .to_s method of the object +puts object.inspect # Inspects the object and prints it out (includes the attributes) +pp object # Pretty Prints the inspected object (like .inspect but better) +``` + +In the Rails application you can use the logger for the output: + +```ruby +Rails.logger object.inspect +``` + +If that's not enough and you want to run a debugger, the `byebug` gem is included for that. Add `byebug` wherever you want a breakpoint and then run the code. + +Caveat: You might have to stop spring (`bin/spring stop`) or restart the server to get it to execute the breakpoint. + +### Debugging JS + +While running the application, you can debug the javascript using your favorite tool, the way you've always done it. + +The javascript files will be concatenated into one file, using the rails asset pipeline. + +You can turn that off by toggling the following flag in `config/environment/development.rb`: + +```ruby +# config.assets.debug = true +config.assets.debug = false +``` + +to + +```ruby +config.assets.debug = true +# config.assets.debug = false +``` + +Because there are too many Angular JS files in this application, and in `debug` mode Rails will try to load every file separately, that slows down the application, and becomes really annoying in development mode to wait for the scripts to load. Which is why it is turned off by default. + +**PS:** Don't forget to restart the server when you change the config. + +## Convenience Scripts + +This application has two ways of running scripts: `rake` & `thor`. + +Rake is great for simple tasks that depend on the application environment, and default tasks that come by default with Rails. + +Whereas Thor is a more powerful tool for writing scripts that take in args much more nicely than Rake. + +### Rake + +To see what rake tasks are available run: + +``` +bin/rake -T +``` + +**Note**: the use of `bin/rake` makes sure that the version of `rake` that is running is the one locked to the app's `Gemfile.lock` (to avoid conflicts with other versions that might be installed on your system). This is equivalent of `bundle exec rake`. + +Common rake tasks that you might use: + +``` +# db +bin/rake db:create +bin/rake db:drop +bin/rake db:migrate +bin/rake db:rollback +bin/rake db:schema:load +bin/rake db:seed +bin/rake db:setup + +# show routes +bin/rake routes + +# tests +bin/rake test +bin/rake test:js +bin/rake test:jshint +bin/rake test:quepid +``` + +### Thor + +The see available tasks: + +``` +thor list +``` + +Examples include: + +``` +case +---- +thor case:share CASEID TEAMID # shares case with an team + +ratings +------- +thor ratings:generate SOLRURL FILENAME # generates random ratings into a .csv file +thor ratings:import CASEID FILENAME # imports ratings to a case + +user +---- +thor user:create USERNAME PASSWORD # creates a new user +thor user:reset_password USERNAME NEWPASSWORD # resets user's password +``` + +To see more details about any of the tasks, run `thor help TASKNAME`: + +``` +thor help user:create +Usage: + thor user:create USERNAME PASSWORD + +Options: + -p, [--paid], [--no-paid] + +Description: + `user:create` creates a new user with the passed in username and password. + + EXAMPLES: + + $ thor user:create foo@example.com mysuperstrongpassword + + With -p option, will mark the user as paid + + EXAMPLES: + + $ thor user:create -p foo@example.com mysuperstrongpassword +``` + +# Elasticsearch + +You will need to configure Elasticsearch to accept requests from the browser using [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing). To enable CORS, add the following to elasticsearch's config file. Usually, this file is located near the elasticsearch executable at `config/elasticsearch.yml`. + +```yml +http.cors: + enabled: true + allow-origin: /https?:\/\/localhost(:[0-9]+)?/ +``` + +# Dev Errata + +## I'd like to use a new Node module + +Typically you would simply do: + +``` +yarn add foobar +``` + +which will install the new Node module, and then save that dependency to `package.json`. + +## I'd like to test SSL + +There's a directory `.ssl` that contains they key and cert files used for SSL. This is a self signed generated certificate for use in development ONLY! + +The key/cert were generated using the following command: + +``` +openssl req -new -newkey rsa:2048 -sha1 -days 365 -nodes -x509 -keyout .ssl/localhost.key -out .ssl/localhost.crt +``` + +**PS:** It is not necessary to do that again. + +What you need to do: + +1. Drag `.ssl/localhost.crt` to `System` in `Keychain Access` (this is for OS X) +2. run (this is for Ubuntu/Vagrant): + * `sudo cp .ssl/localhost.crt /etc/ssl/cert` + * `sudo cp .ssl/localhost.key /etc/ssl/private` + * `sudo c_rehash` +3. In `Procfile` comment the part that uses `puma` and uncomment the part that uses `thin` +4. In `.env` make sure you add `FORCE_SSL=true` +5. Restart the server +6. Go to `https://localhost:3000` + +**PS:** Why are we using both `puma` and `thin`? Because I simply could not figure out how to get `puma` to work properly with SSL and did not want to spend any more time on it! + +# QA + +There is a code deployment pipeline to the staging-quepid.herokuapp.com site. + +## Seed Data + +The following accounts are created through the seeds. The all follow the following format: + +``` +username: quepid+[type]@o19s.com +password: quepid+[type] +``` + +where type is one of the following: + +* `admin`: An admin account +* `1case`: A trial user with 1 case +* `2case`: A trial user with 2 cases +* `solr`: A trial user with a Solr case +* `es`: A trial user with a ES case +* `10sOfQueries`: A trial user with a Solr case that has 10s of queries +* `100sOfQueries`: A trial user with a Solr case that has 100s of queries (usually disabled) +* `1000sOfQueries`: A trial user with a Solr case that has 1000s of queries (usually disabled) +* `oscOwner`: A trial user who owns the team 'OSC' +* `oscMember`: A trial user who is a member of the team 'OSC' +* `enterpriseOwner`: A trial user who owns the enterprise 'OSC E' +* `enterpriseMember`: A trial user who is a member of the enterprise 'OSC E' +* `CustomScorer`: A trial user who has a custom scorer +* `CustomScorerDefault`: A trial user who has a custom scorer that is set as their default + +# Data Map + +Check out the [Data Mapping](docs/data_mapping.md) file for more info about the data structure of the app. + +# App Structure + +Check out the [App Structure](docs/app_structure.md) file for more info on how the app is structured. + +# Legal Pages + +If you would like to have legal pages linked in the footer of the app, add the following `ENV` vars: + +``` +TC_URL # terms and condition +PRIVACY_URL # privacy policy +COOKIES_URL # cookies policy +``` diff --git a/Rakefile b/Rakefile new file mode 100755 index 000000000..e51cf0e17 --- /dev/null +++ b/Rakefile @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +# 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', __dir__) + +Rails.application.load_tasks diff --git a/app.json b/app.json new file mode 100644 index 000000000..8209da4e1 --- /dev/null +++ b/app.json @@ -0,0 +1,80 @@ +{ + "addons": [ + "jawsdb", + "logdna", + "heroku-redis" + ], + "buildpacks": [ + { + "url": "heroku/nodejs" + }, + { + "url": "heroku/ruby" + } + ], + "env": { + "BUNDLE_WITHOUT": { + "required": true + }, + "DB_ADAPTER": { + "required": true + }, + "FORCE_SSL": { + "required": true + }, + "INTERCOM_API_KEY": { + "required": true + }, + "INTERCOM_APP_ID": { + "required": true + }, + "LANG": { + "required": true + }, + "LOGDNA_KEY": { + "required": true + }, + "POSTMARK_API_TOKEN": { + "required": true + }, + "QUEPID_DOMAIN": { + "required": true + }, + "QUEPID_GA": { + "required": true + }, + "RACK_ENV": { + "required": true + }, + "RAILS_ENV": { + "required": true + }, + "RAILS_SERVE_STATIC_FILES": { + "required": true + }, + "SECRET_KEY_BASE": { + "generator": "secret" + }, + "SIDEKIQ_CONCURRENCY": { + "required": true + }, + "STRIPE_PUBLISHABLE_KEY": { + "required": true + }, + "STRIPE_SECRET_KEY": { + "required": true + } + }, + "formation": { + "worker": { + "quantity": 1 + }, + "web": { + "quantity": 1 + } + }, + "name": "quepid", + "scripts": { + }, + "stack": "heroku-16" +} diff --git a/app/assets/fonts/aller_bd-webfont.eot b/app/assets/fonts/aller_bd-webfont.eot new file mode 100755 index 000000000..6984ec4b5 Binary files /dev/null and b/app/assets/fonts/aller_bd-webfont.eot differ diff --git a/app/assets/fonts/aller_bd-webfont.svg b/app/assets/fonts/aller_bd-webfont.svg new file mode 100755 index 000000000..76aa4a33e --- /dev/null +++ b/app/assets/fonts/aller_bd-webfont.svg @@ -0,0 +1,256 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/assets/fonts/aller_bd-webfont.ttf b/app/assets/fonts/aller_bd-webfont.ttf new file mode 100755 index 000000000..43cd53011 Binary files /dev/null and b/app/assets/fonts/aller_bd-webfont.ttf differ diff --git a/app/assets/fonts/aller_bd-webfont.woff b/app/assets/fonts/aller_bd-webfont.woff new file mode 100755 index 000000000..8bb7566fd Binary files /dev/null and b/app/assets/fonts/aller_bd-webfont.woff differ diff --git a/app/assets/fonts/aller_bdit-webfont.eot b/app/assets/fonts/aller_bdit-webfont.eot new file mode 100755 index 000000000..527c6b795 Binary files /dev/null and b/app/assets/fonts/aller_bdit-webfont.eot differ diff --git a/app/assets/fonts/aller_bdit-webfont.svg b/app/assets/fonts/aller_bdit-webfont.svg new file mode 100755 index 000000000..bc2d21556 --- /dev/null +++ b/app/assets/fonts/aller_bdit-webfont.svg @@ -0,0 +1,258 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/assets/fonts/aller_bdit-webfont.ttf b/app/assets/fonts/aller_bdit-webfont.ttf new file mode 100755 index 000000000..5186902f9 Binary files /dev/null and b/app/assets/fonts/aller_bdit-webfont.ttf differ diff --git a/app/assets/fonts/aller_bdit-webfont.woff b/app/assets/fonts/aller_bdit-webfont.woff new file mode 100755 index 000000000..5d2a2728d Binary files /dev/null and b/app/assets/fonts/aller_bdit-webfont.woff differ diff --git a/app/assets/fonts/aller_it-webfont.eot b/app/assets/fonts/aller_it-webfont.eot new file mode 100755 index 000000000..b9c639149 Binary files /dev/null and b/app/assets/fonts/aller_it-webfont.eot differ diff --git a/app/assets/fonts/aller_it-webfont.svg b/app/assets/fonts/aller_it-webfont.svg new file mode 100755 index 000000000..f9b72706b --- /dev/null +++ b/app/assets/fonts/aller_it-webfont.svg @@ -0,0 +1,256 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/assets/fonts/aller_it-webfont.ttf b/app/assets/fonts/aller_it-webfont.ttf new file mode 100755 index 000000000..be3ffb512 Binary files /dev/null and b/app/assets/fonts/aller_it-webfont.ttf differ diff --git a/app/assets/fonts/aller_it-webfont.woff b/app/assets/fonts/aller_it-webfont.woff new file mode 100755 index 000000000..07994059f Binary files /dev/null and b/app/assets/fonts/aller_it-webfont.woff differ diff --git a/app/assets/fonts/aller_rg-webfont.eot b/app/assets/fonts/aller_rg-webfont.eot new file mode 100755 index 000000000..ae9d44a5a Binary files /dev/null and b/app/assets/fonts/aller_rg-webfont.eot differ diff --git a/app/assets/fonts/aller_rg-webfont.svg b/app/assets/fonts/aller_rg-webfont.svg new file mode 100755 index 000000000..36c29b017 --- /dev/null +++ b/app/assets/fonts/aller_rg-webfont.svg @@ -0,0 +1,256 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/assets/fonts/aller_rg-webfont.ttf b/app/assets/fonts/aller_rg-webfont.ttf new file mode 100755 index 000000000..055d469aa Binary files /dev/null and b/app/assets/fonts/aller_rg-webfont.ttf differ diff --git a/app/assets/fonts/aller_rg-webfont.woff b/app/assets/fonts/aller_rg-webfont.woff new file mode 100755 index 000000000..0bc885ba2 Binary files /dev/null and b/app/assets/fonts/aller_rg-webfont.woff differ diff --git a/app/assets/fonts/chunkfive.eot b/app/assets/fonts/chunkfive.eot new file mode 100755 index 000000000..cbb2903e9 Binary files /dev/null and b/app/assets/fonts/chunkfive.eot differ diff --git a/app/assets/fonts/chunkfive.svg b/app/assets/fonts/chunkfive.svg new file mode 100755 index 000000000..f7d37c5df --- /dev/null +++ b/app/assets/fonts/chunkfive.svg @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/assets/fonts/chunkfive.ttf b/app/assets/fonts/chunkfive.ttf new file mode 100755 index 000000000..f17a23e32 Binary files /dev/null and b/app/assets/fonts/chunkfive.ttf differ diff --git a/app/assets/fonts/chunkfive.woff b/app/assets/fonts/chunkfive.woff new file mode 100755 index 000000000..9177b7174 Binary files /dev/null and b/app/assets/fonts/chunkfive.woff differ diff --git a/app/assets/images/.keep b/app/assets/images/.keep new file mode 100755 index 000000000..e69de29bb diff --git a/app/assets/images/OSC-icon.png b/app/assets/images/OSC-icon.png new file mode 100644 index 000000000..cda51e706 Binary files /dev/null and b/app/assets/images/OSC-icon.png differ diff --git a/app/assets/images/OSC_logo_small.png b/app/assets/images/OSC_logo_small.png new file mode 100644 index 000000000..c95061676 Binary files /dev/null and b/app/assets/images/OSC_logo_small.png differ diff --git a/app/assets/images/OSC_logo_tiny.png b/app/assets/images/OSC_logo_tiny.png new file mode 100644 index 000000000..8463c619f Binary files /dev/null and b/app/assets/images/OSC_logo_tiny.png differ diff --git a/app/assets/images/Solr.png b/app/assets/images/Solr.png new file mode 100644 index 000000000..05f1abd4e Binary files /dev/null and b/app/assets/images/Solr.png differ diff --git a/app/assets/images/blue_bg.gif b/app/assets/images/blue_bg.gif new file mode 100644 index 000000000..3c81c6efc Binary files /dev/null and b/app/assets/images/blue_bg.gif differ diff --git a/app/assets/images/blue_bg.jpg b/app/assets/images/blue_bg.jpg new file mode 100644 index 000000000..21d14abcd Binary files /dev/null and b/app/assets/images/blue_bg.jpg differ diff --git a/app/assets/images/cta_texture.gif b/app/assets/images/cta_texture.gif new file mode 100644 index 000000000..65abe5224 Binary files /dev/null and b/app/assets/images/cta_texture.gif differ diff --git a/app/assets/images/custom_scorer.gif b/app/assets/images/custom_scorer.gif new file mode 100644 index 000000000..ae73467e4 Binary files /dev/null and b/app/assets/images/custom_scorer.gif differ diff --git a/app/assets/images/custom_test.gif b/app/assets/images/custom_test.gif new file mode 100644 index 000000000..30abb39f9 Binary files /dev/null and b/app/assets/images/custom_test.gif differ diff --git a/app/assets/images/custom_test.png b/app/assets/images/custom_test.png new file mode 100644 index 000000000..317f3e242 Binary files /dev/null and b/app/assets/images/custom_test.png differ diff --git a/app/assets/images/dog_query.png b/app/assets/images/dog_query.png new file mode 100644 index 000000000..696c017d4 Binary files /dev/null and b/app/assets/images/dog_query.png differ diff --git a/app/assets/images/doug.jpg b/app/assets/images/doug.jpg new file mode 100644 index 000000000..f13d5b9fe Binary files /dev/null and b/app/assets/images/doug.jpg differ diff --git a/app/assets/images/dropdown-arrow.png b/app/assets/images/dropdown-arrow.png new file mode 100644 index 000000000..74003ec6b Binary files /dev/null and b/app/assets/images/dropdown-arrow.png differ diff --git a/app/assets/images/elasticsearch.png b/app/assets/images/elasticsearch.png new file mode 100644 index 000000000..36efbf756 Binary files /dev/null and b/app/assets/images/elasticsearch.png differ diff --git a/app/assets/images/favicon.ico b/app/assets/images/favicon.ico new file mode 100644 index 000000000..13f1bebe8 Binary files /dev/null and b/app/assets/images/favicon.ico differ diff --git a/app/assets/images/home-bg.jpg b/app/assets/images/home-bg.jpg new file mode 100644 index 000000000..b49c6952d Binary files /dev/null and b/app/assets/images/home-bg.jpg differ diff --git a/app/assets/images/home-main.png b/app/assets/images/home-main.png new file mode 100644 index 000000000..2e198ad80 Binary files /dev/null and b/app/assets/images/home-main.png differ diff --git a/app/assets/images/logo.png b/app/assets/images/logo.png new file mode 100644 index 000000000..3cd3bc999 Binary files /dev/null and b/app/assets/images/logo.png differ diff --git a/app/assets/images/main-bg.jpg b/app/assets/images/main-bg.jpg new file mode 100644 index 000000000..19e71e47d Binary files /dev/null and b/app/assets/images/main-bg.jpg differ diff --git a/app/assets/images/screenshot.png b/app/assets/images/screenshot.png new file mode 100644 index 000000000..db514e7de Binary files /dev/null and b/app/assets/images/screenshot.png differ diff --git a/app/assets/images/select-arrow.png b/app/assets/images/select-arrow.png new file mode 100644 index 000000000..0da3effbf Binary files /dev/null and b/app/assets/images/select-arrow.png differ diff --git a/app/assets/images/settings-icon.png b/app/assets/images/settings-icon.png new file mode 100644 index 000000000..a95014173 Binary files /dev/null and b/app/assets/images/settings-icon.png differ diff --git a/app/assets/images/sidebar.png b/app/assets/images/sidebar.png new file mode 100644 index 000000000..74ebb2fee Binary files /dev/null and b/app/assets/images/sidebar.png differ diff --git a/app/assets/images/sub-results-bg.png b/app/assets/images/sub-results-bg.png new file mode 100644 index 000000000..42328978f Binary files /dev/null and b/app/assets/images/sub-results-bg.png differ diff --git a/app/assets/images/tagline-sm.png b/app/assets/images/tagline-sm.png new file mode 100644 index 000000000..f6d3a7439 Binary files /dev/null and b/app/assets/images/tagline-sm.png differ diff --git a/app/assets/images/tagline.png b/app/assets/images/tagline.png new file mode 100644 index 000000000..376cdccea Binary files /dev/null and b/app/assets/images/tagline.png differ diff --git a/app/assets/images/video-callout.png b/app/assets/images/video-callout.png new file mode 100644 index 000000000..3a773bcfc Binary files /dev/null and b/app/assets/images/video-callout.png differ diff --git a/app/assets/javascripts/accounts.js b/app/assets/javascripts/accounts.js new file mode 100644 index 000000000..d52c9e241 --- /dev/null +++ b/app/assets/javascripts/accounts.js @@ -0,0 +1,5 @@ +//= require jquery +//= require bootstrap-sprockets +//= require jquery_ujs +//= require jquery-ui +//= require bootstrap diff --git a/app/assets/javascripts/ace_config.js b/app/assets/javascripts/ace_config.js new file mode 100644 index 000000000..da96915d7 --- /dev/null +++ b/app/assets/javascripts/ace_config.js @@ -0,0 +1,109 @@ +'use strict'; + +/*global ace */ +ace.config.set('workerPath', '/javascripts/ace'); +ace.config.set('themePath', '/javascripts/ace'); + +$(function() { + + // For some reason when angular is in charge of refreshing the DOM, + // the old height of the element is the one that's being returned. + // So we need to tell it to "refetch" the element from the DOM to refresh + // and get the new height. + // WEIRD.... + var $element = $('#query-params-editor'); + var lastHeight = $element.height(); + var margin = 50; + function checkForChanges() + { + $element = $('#query-params-editor'); + if ($element.height() !== lastHeight) + { + $(document).trigger('devSettingsHeightChange'); + lastHeight = $element.height(); + } + + setTimeout(checkForChanges, 500); + } + checkForChanges(); + + function resizeAce() { + var height = $('#query-params-editor').height(); + if ( height === null ) { + setTimeout(function () { + resizeAce(); + }, 200); + return; + } + + $('.es-query-params').height(height - margin); + + // delay, because... computers! + // if on another page (/cases, or /teams) and switch to case page, + // then for some reason `$('#query-params-editor').height()` returns 100 + // when toggling the pane ON, and the right size when OFF!!! + // a 100ms delay creates some weird behavior in the ace editor. + // 200ms works just fine. GO FIGURE! + setTimeout(function () { + $('.es-query-params').height(height - margin); + + // must repaint the editor, or else.... BOOM! + if ( $('#es-query-params-editor').length > 0 ) { + var editor = ace.edit('es-query-params-editor'); + editor.resize(); + } + }, 200); + } + + //set initially + resizeAce(); + + //listen for changes + $(window).resize(resizeAce); + $(document).on('toggleEast', resizeAce); + $(document).on('devSettingsHeightChange', resizeAce); + + $('[name="queryParams"]').keyup(function() { + var input = $(this); + var value = input.val(); + + var options = { + container: '.pane_container', + html: true, + placement: 'auto left', + template: '', + title: 'You may have a syntax error ', + trigger: 'manual', + }; + + var params = { + deftype: 'defType', + echoparams: 'echoParams', + explainother: 'explainOther', + logparamslist: 'logParamsList', + omitheader: 'omitHeader', + segmentterminateearly: 'segmentTerminateEarly', + timeallowed: 'timeAllowed', + }; + + var warn = false; + + for (var key in params) { + var correct = params[key]; + var re = new RegExp(key); + + if ( value.match(re) ) { + options.content = 'You query params contain ' + key + ', you probably meant ' + correct + ''; + warn = true; + break; + } + } + + if ( warn ) { + input.popover(options); + input.popover('show'); + } else { + input.popover('destroy'); + } + }); +}); diff --git a/app/assets/javascripts/admin.js b/app/assets/javascripts/admin.js new file mode 100644 index 000000000..8c57ebe59 --- /dev/null +++ b/app/assets/javascripts/admin.js @@ -0,0 +1,11 @@ +//= require jquery +//= require bootstrap-sprockets +//= require jquery_ujs +//= require jquery-ui +//= require d3 +//= require cal-heatmap +//= require ace-rails-ap +//= require ace/theme-chrome +//= require ace/mode-javascript +//= require admin/scorers +//= require admin/user_pulse diff --git a/app/assets/javascripts/admin/scorers.js b/app/assets/javascripts/admin/scorers.js new file mode 100644 index 000000000..55685c2be --- /dev/null +++ b/app/assets/javascripts/admin/scorers.js @@ -0,0 +1,64 @@ +'use strict'; + +/*global ace */ + +$(function() { + $.each($('.scorer .code > div'), function(index, element) { + var id = $(element).attr('id'); + var readonly = $(element).data('readonly'); + + var code = $(element).data('code').replace(/\n/g, '\n'); + var codeArray = code.split('\\n'); + code = codeArray.join('\n'); + + var editor = ace.edit(id); + editor.setTheme('ace/theme/chrome'); + editor.getSession().setMode('ace/mode/javascript'); + editor.setValue(code); + + if ( readonly !== undefined && readonly ) { + editor.setReadOnly(true); + } + }); + + var codeElement = $('#scorer-code-editor'); + if ( codeElement.length ) { + var code = codeElement.data('code').replace(/\n/g, '\n'); + var codeArray = code.split('\\n'); + code = codeArray.join('\n'); + var editor = ace.edit('scorer-code-editor'); + editor.setTheme('ace/theme/chrome'); + editor.getSession().setMode('ace/mode/javascript'); + editor.setValue(code); + + codeElement.closest('form').submit(function () { + var value = editor.getSession().getValue(); + var valueField = $('#default_scorer_code'); + valueField.val(value); + }); + } + + var scaleElement = $('input[data-live-update]'); + if ( scaleElement.length ) { + scaleElement.on('change', function() { + var labelsId = scaleElement.data('live-update'); + var values = scaleElement.val().replace(/,\s*$/, '').split(','); + var labels = $('#' + labelsId); + + labels.empty(); + $.each(values, function(key, value) { + var input = $('') + .addClass('scale-with-label-element clearfix') + .append($('') + .attr({ + type: 'text', + name: 'default_scorer[scale_with_labels][' + value + ']' + }) + .addClass('form-control scale-label clearfix') + ); + + labels.append(input); + }); + }); + } +}); diff --git a/app/assets/javascripts/admin/user_pulse.coffee b/app/assets/javascripts/admin/user_pulse.coffee new file mode 100644 index 000000000..bed46a883 --- /dev/null +++ b/app/assets/javascripts/admin/user_pulse.coffee @@ -0,0 +1,26 @@ +do -> + 'use strict' + + $('[data-pulse]').each -> + div = $(this) + selector = div.data('item-selector') + url = div.data('url') + date = div.data('signup-date') + signup_date = new Date(date) + + now = new Date + start_date = new Date 1900+now.getYear(), now.getMonth() - 11, 1 + + cal = new CalHeatMap() + cal.init { + cellSize: 20, + data: "#{url}&start={{d:start}}&end={{d:end}}", + dataType: 'json', + domain: 'month', + highlight: [ 'now', signup_date], + itemSelector: selector, + start: start_date, + subDomain: 'day', + } + + return diff --git a/app/assets/javascripts/app.js b/app/assets/javascripts/app.js new file mode 100644 index 000000000..519f42b43 --- /dev/null +++ b/app/assets/javascripts/app.js @@ -0,0 +1,22 @@ +'use strict'; + +angular.module('QuepidApp', [ + 'yaru22.angular-timeago', + 'UtilitiesModule', + 'ngRoute', + 'ngCookies', + 'ngSanitize', + 'ui.bootstrap', + 'mgo-angular-wizard', + 'ui.sortable', + 'ngJsonExplorer', + 'o19s.splainer-search', + 'ui.ace', + 'angularUtils.directives.dirPagination', + 'ngCsvImport', + 'angular-flash.service', + 'angular-flash.flash-alert-directive', + 'ngTagsInput', + 'ng-rails-csrf', + 'templates' +]); diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js new file mode 100755 index 000000000..4677572df --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,65 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, +// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. +// +// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details +// about supported directives. +// +//= require jquery +//= require bootstrap-sprockets +//= require jquery_ujs +//= require jquery-ui +//= require jquery-autoGrowInput +//= require d3 +//= require d3-tip +//= require cookies_eu +//= require angular/angular +//= require ace-builds/src-min-noconflict/ace +//= require ace-builds/src-min-noconflict/ext-language_tools +//= require ace-builds/src-min-noconflict/mode-json +//= require ace-builds/src-min-noconflict/mode-javascript +//= require bootstrap/dist/js/bootstrap +//= require angular-resource/angular-resource +//= require angular-cookies/angular-cookies +//= require angular-route/angular-route +//= require angular-sanitize/angular-sanitize +//= require angular-ui-bootstrap/dist/ui-bootstrap +//= require angular-ui-bootstrap/dist/ui-bootstrap-tpls +//= require angular-wizard/dist/angular-wizard +//= require angular-rails-templates +//= require splainer-search/splainer-search +//= require ng-json-explorer/dist/angular-json-explorer +//= require angular-ui-ace/src/ui-ace +//= require angular-ui-sortable/dist/sortable +//= require angular-utils-pagination/dirPagination +//= require angular-timeago/src/timeAgo +//= require angular-csv-import/dist/angular-csv-import +//= require angular-flash/dist/angular-flash +//= require ng-tags-input/build//ng-tags-input +//= require FileSaver.js/FileSaver +//= require urijs/src/URI +//= require utilitiesModule +//= require secureApp +//= require bind +//= require app +//= require routes +//= require_tree ./components +//= require_tree ./controllers +//= require_tree ./directives +//= require_tree ./factories +//= require_tree ./filters +//= require_tree ./interceptors +//= require_tree ./services +//= require_tree ./values +//= require_tree ../templates +//= require_tree ./components +//= require ace_config +//= require footer +//= require tether-shepherd/dist/js/tether +//= require tether-shepherd/dist/js/shepherd +//= require tour diff --git a/app/assets/javascripts/bind.js b/app/assets/javascripts/bind.js new file mode 100644 index 000000000..f64ae9e24 --- /dev/null +++ b/app/assets/javascripts/bind.js @@ -0,0 +1,30 @@ +'use strict'; + +/* Some browsers and PhantomJS don't support bind, mozilla provides + * this implementation as a monkey patch on Function.prototype + * + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FFunction%2Fbind + */ + +if (!Function.prototype.bind) { + Function.prototype.bind = function (oThis) { + if (typeof this !== 'function') { + // closest thing possible to the ECMAScript 5 internal IsCallable function + throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); + } + + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + FNOP = function () {}, + fBound = function () { + return fToBind.apply(this instanceof FNOP && oThis ? this + : oThis, + aArgs.concat(Array.prototype.slice.call(arguments))); + }; + + FNOP.prototype = this.prototype; + fBound.prototype = new FNOP(); + + return fBound; + }; +} diff --git a/app/assets/javascripts/components/action_icon/action_icon.html b/app/assets/javascripts/components/action_icon/action_icon.html new file mode 100644 index 000000000..7cbdc99b0 --- /dev/null +++ b/app/assets/javascripts/components/action_icon/action_icon.html @@ -0,0 +1,8 @@ + + + diff --git a/app/assets/javascripts/components/action_icon/action_icon_controller.js b/app/assets/javascripts/components/action_icon/action_icon_controller.js new file mode 100644 index 000000000..0dbe603c9 --- /dev/null +++ b/app/assets/javascripts/components/action_icon/action_icon_controller.js @@ -0,0 +1,14 @@ +'use strict'; + +/*jslint latedef:false*/ + +angular.module('QuepidApp') + .controller('ActionIconCtrl', [ + '$scope', + function ( $scope ) { + var ctrl = this; + ctrl.fnCall = $scope.fnCall; + ctrl.iconClass = $scope.iconClass; + ctrl.title = $scope.title; + } + ]); diff --git a/app/assets/javascripts/components/action_icon/action_icon_directive.js b/app/assets/javascripts/components/action_icon/action_icon_directive.js new file mode 100644 index 000000000..bf48dbe32 --- /dev/null +++ b/app/assets/javascripts/components/action_icon/action_icon_directive.js @@ -0,0 +1,18 @@ +'use strict'; + +angular.module('QuepidApp') + .directive('actionIcon', [ + function () { + return { + restrict: 'E', + controller: 'ActionIconCtrl', + controllerAs: 'ctrl', + templateUrl: 'action_icon/action_icon.html', + scope: { + fnCall: '&', + iconClass: '=', + title: '=', + }, + }; + } + ]); diff --git a/app/assets/javascripts/components/ad_hoc_scorer/ad_hoc_scorer.html b/app/assets/javascripts/components/ad_hoc_scorer/ad_hoc_scorer.html new file mode 100644 index 000000000..a747a19a2 --- /dev/null +++ b/app/assets/javascripts/components/ad_hoc_scorer/ad_hoc_scorer.html @@ -0,0 +1 @@ + diff --git a/app/assets/javascripts/components/ad_hoc_scorer/ad_hoc_scorer_controller.js b/app/assets/javascripts/components/ad_hoc_scorer/ad_hoc_scorer_controller.js new file mode 100644 index 000000000..a9727926c --- /dev/null +++ b/app/assets/javascripts/components/ad_hoc_scorer/ad_hoc_scorer_controller.js @@ -0,0 +1,40 @@ +'use strict'; + +/*jslint latedef:false*/ + +angular.module('QuepidApp') + .controller('AdHocScorerCtrl', [ + '$scope', + 'scorerControllerActionsSvc', + 'customScorerSvc', + function ( + $scope, + scorerControllerActionsSvc, + customScorerSvc + ) { + var ctrl = this; + ctrl.scorer = $scope.scorer; + + scorerControllerActionsSvc.addActions(ctrl, $scope); + + if (customScorerSvc.scalesAreEqual( + ctrl.scorer.scale, ctrl.scaleOptions.defaultScale + )) { + ctrl.scaleChoice = 'defaultScale'; + } else if (customScorerSvc.scalesAreEqual( + ctrl.scorer.scale, ctrl.scaleOptions.shortScale + )) { + ctrl.scaleChoice = 'shortScale'; + } else if (customScorerSvc.scalesAreEqual( + ctrl.scorer.scale, ctrl.scaleOptions.fibonacciScale + )) { + ctrl.scaleChoice = 'fibonacciScale'; + } else { + ctrl.scaleChoice = 'custom'; + } + + ctrl.scorerOptions = { + showName: false + }; + } + ]); diff --git a/app/assets/javascripts/components/ad_hoc_scorer/ad_hoc_scorer_directive.js b/app/assets/javascripts/components/ad_hoc_scorer/ad_hoc_scorer_directive.js new file mode 100644 index 000000000..7e0dcb05d --- /dev/null +++ b/app/assets/javascripts/components/ad_hoc_scorer/ad_hoc_scorer_directive.js @@ -0,0 +1,16 @@ +'use strict'; + +angular.module('QuepidApp') + .directive('adHocScorer', [ + function () { + return { + restrict: 'E', + controller: 'AdHocScorerCtrl', + controllerAs: 'ctrl', + templateUrl: 'ad_hoc_scorer/ad_hoc_scorer.html', + scope: { + scorer: '=', + }, + }; + } + ]); diff --git a/app/assets/javascripts/components/add_member/add_member.html b/app/assets/javascripts/components/add_member/add_member.html new file mode 100644 index 000000000..6cf9cce84 --- /dev/null +++ b/app/assets/javascripts/components/add_member/add_member.html @@ -0,0 +1,28 @@ + + +
+ + + + Add + + +

+ Start typing a username to add user as a member to this team. + Once you select a user, click on "Add" to add them as a member. +

+
diff --git a/app/assets/javascripts/components/add_member/add_member_controller.js b/app/assets/javascripts/components/add_member/add_member_controller.js new file mode 100644 index 000000000..2ad0f87ae --- /dev/null +++ b/app/assets/javascripts/components/add_member/add_member_controller.js @@ -0,0 +1,57 @@ +'use strict'; + +/*jshint latedef:false */ + +angular.module('QuepidApp') + .controller('AddMemberCtrl', [ + '$scope', + 'flash', + 'teamSvc', 'userSvc', + function ( + $scope, + flash, + teamSvc, userSvc + ) { + var ctrl = this; + + $scope.$watch('team', function() { + ctrl.team = $scope.team; + }); + + // Functions + ctrl.addMember = addMember; + ctrl.getUsers = getUsers; + ctrl.selectMember = selectMember; + + function selectMember($item) { + ctrl.selectedMember = $item; + } + + function addMember() { + if ( angular.isDefined(ctrl.selectedMember) ) { + teamSvc.addMember(ctrl.team, ctrl.selectedMember) + .then(function() { + flash.success = 'New member added'; + ctrl.selected = ''; + }, function(response) { + flash.error = response.data.error; + }); + } else { + teamSvc.addMemberByEmail(ctrl.team, ctrl.selected) + .then(function() { + flash.success = 'New member added'; + ctrl.selected = ''; + }, function(response) { + flash.error = response.data.error; + }); + } + } + + function getUsers(val) { + return userSvc.users(val) + .then(function(response) { + return response.data.users; + }); + } + } + ]); diff --git a/app/assets/javascripts/components/add_member/add_member_directive.js b/app/assets/javascripts/components/add_member/add_member_directive.js new file mode 100644 index 000000000..b71bb96f8 --- /dev/null +++ b/app/assets/javascripts/components/add_member/add_member_directive.js @@ -0,0 +1,16 @@ +'use strict'; + +angular.module('QuepidApp') + .directive('addMember', [ + function () { + return { + restrict: 'E', + controller: 'AddMemberCtrl', + controllerAs: 'ctrl', + templateUrl: 'add_member/add_member.html', + scope: { + team: '=', + }, + }; + } + ]); diff --git a/app/assets/javascripts/components/add_query/add_query.html b/app/assets/javascripts/components/add_query/add_query.html new file mode 100644 index 000000000..21d784148 --- /dev/null +++ b/app/assets/javascripts/components/add_query/add_query.html @@ -0,0 +1,20 @@ +
+ + + + + +
diff --git a/app/assets/javascripts/components/add_query/add_query_controller.js b/app/assets/javascripts/components/add_query/add_query_controller.js new file mode 100644 index 000000000..8aca162f3 --- /dev/null +++ b/app/assets/javascripts/components/add_query/add_query_controller.js @@ -0,0 +1,109 @@ +'use strict'; + +/* jshint latedef:false */ + +angular.module('QuepidApp') + .controller('AddQueryCtrl', [ + '$rootScope', + '$timeout', + 'flash', + 'queriesSvc', + function ( + $rootScope, + $timeout, + flash, + queriesSvc + ) { + var ctrl = this; + var delim = ';'; + + ctrl.text = ''; + ctrl.loading = false; + + // Functions + ctrl.handlePaste = handlePaste; + ctrl.message = message; + ctrl.submit = submit; + + var addOne = function(queryText, user) { + var q = queriesSvc.createQuery(queryText); + + queriesSvc.persistQuery(q) + .then(function() { + q.search() + .then(function success() { + flash.success = 'Query added successfully.'; + }, function error(errorMsg) { + flash.error = 'Your new query had an error!'; + flash.to('search-error').error = errorMsg; + }); + + user.queryAdded(); + ctrl.loading = false; + }); + }; + + var addMany = function(queryTexts, user) { + var queries = []; + + angular.forEach(queryTexts, function(queryText) { + queries.push(queriesSvc.createQuery(queryText)); + }); + + queriesSvc.persistQueries(queries) + .then(function() { + queriesSvc.searchAll() + .then(function () { + flash.success = 'Queries added successfull.'; + }, function (errorMsg) { + flash.error = 'One (or many) of your new queries had an error!'; + flash.to('search-error').error = errorMsg; + }); + + user.queryAdded(queries.length); + ctrl.loading = false; + }); + }; + + var userQueries = function(searchStrings) { + return searchStrings; + }; + + var parseAddQuery = function(formInput) { + var newQueries = []; + + angular.forEach(formInput.split(delim), function(newQuery) { + var trimmed = newQuery.replace(/(^\s+|\s+$)/g,''); + if (trimmed.length > 0) { + newQueries.push(trimmed); + } + }); + + return newQueries; + }; + + function submit () { + ctrl.loading = true; + var initialSearchStrings = parseAddQuery(ctrl.text); + var searchStrings = userQueries(initialSearchStrings, $rootScope.currentUser); + + if ( searchStrings.length === 1 ) { + addOne(searchStrings[0], $rootScope.currentUser); + } else if ( searchStrings.length > 1 ) { + addMany(searchStrings, $rootScope.currentUser); + } + + ctrl.text = ''; + } + + function handlePaste(pastedText) { + $timeout(function() { + ctrl.text = pastedText.split('\n').join(delim); + }); + } + + function message() { + return 'Add a query to this case'; + } + } + ]); diff --git a/app/assets/javascripts/components/add_query/add_query_directive.js b/app/assets/javascripts/components/add_query/add_query_directive.js new file mode 100644 index 000000000..0adc5252d --- /dev/null +++ b/app/assets/javascripts/components/add_query/add_query_directive.js @@ -0,0 +1,13 @@ +'use strict'; + +angular.module('QuepidApp') + .directive('addQuery', [ + function() { + return { + scope: true, + controller: 'AddQueryCtrl', + controllerAs: 'ctrl', + templateUrl: 'add_query/add_query.html', + }; + } + ]); diff --git a/app/assets/javascripts/components/annotation/_update.html b/app/assets/javascripts/components/annotation/_update.html new file mode 100644 index 000000000..50ac95193 --- /dev/null +++ b/app/assets/javascripts/components/annotation/_update.html @@ -0,0 +1,18 @@ + + +