Skip to content

Commit

Permalink
Merge branch 'release/0.1.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
akhilgkrishnan committed Mar 15, 2022
2 parents e9f9e6c + 98dcd56 commit ca944be
Show file tree
Hide file tree
Showing 106 changed files with 3,303 additions and 849 deletions.
Binary file modified .DS_Store
Binary file not shown.
15 changes: 8 additions & 7 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# Pull Request Template
## Notion card

## Description

Please include a summary of the change and which issue is fixed. Please also
## Summary
<!-- Please include a summary of the change and which issue is fixed. Please also
include relevant motivation and context. List any dependencies that are required
for this change.
for this change. -->

Fixes # (issue)
## Preview
<!-- Please include a short loom video previewing the changes made in the PR. This will help
the reviewers visualize and get context at a glance -->

## Type of change

Expand All @@ -24,7 +25,7 @@ Please delete options that are not relevant.
instructions so we can reproduce. Please also list any relevant details for your
test configuration -->

## Checklist:
### Checklist:

- [ ] I have manually tested all workflows
- [ ] I have performed a self-review of my own code
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/validations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,11 @@ jobs:
- name: Run Prettier
run: |
npx prettier "./app/javascript/**/*.{ts,tsx,js,jsx,json}"
- name: Cypress install
uses: cypress-io/github-action@v2
with:
# just perform install
runTests: false
- name: Cypress tests
run: |
npm run cy:run:staging
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,8 @@ yarn-debug.log*
# Avoid code coverage report to be pushed to GitHub
/coverage

.idea
.idea

# Ignore cypress screenshots and videos
cypress/artifacts/screenshots
cypress/artifacts/videos
18 changes: 18 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"javascript.format.insertSpaceAfterCommaDelimiter": true,
"javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": true,
"javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": true,
"files.trimFinalNewlines": true,
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
"editor.renderWhitespace": "boundary",
"editor.fontSize": 14,
"editor.rulers": [
100,
120
],
"editor.tabSize": 2,
"javascript.updateImportsOnFileMove.enabled": "never",
"workbench.iconTheme": "material-icon-theme",
"workbench.colorTheme": "Oceanic Plus"
}
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,48 @@ add `EMAIL_DELIVERY_METHOD='letter_opener_web'` to `.env`)
| Owner | [email protected] | password |
| Admin | [email protected] | password |
| Employee | [email protected] | password |

## Installation of Cypress Dependencies

Install the cypress dependencies using the following command:

```sh
cd cypress
yarn install
```

## Running Cypress tests

Cypress tests can be run on local, staging and production environment.

To run the cypress tests on the local environment and in headless mode use the
following command:

```sh
cd cypress
yarn run cy:run:dev
```

To run the tests on local environment and in chrome browser use the following
command:

```sh
cd cypress
yarn run cy:open:dev
```

To run the tests on staging environment and in headless mode use the following
command:

```sh
cd cypress
yarn run cy:run:staging
```

To run the tests on staging environment and in chrome browser use the following
command

```sh
cd cypress
yarn run cy:open:staging
```
4 changes: 4 additions & 0 deletions app/assets/images/checkbox-checked.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions app/assets/images/checkbox-unchecked.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions app/assets/images/company.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions app/assets/images/down_arrow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions app/assets/images/mobile-menu.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions app/assets/images/notification.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion app/assets/images/search_icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion app/controllers/clients_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def create

private
def clients
@_clients ||= current_company.clients.order(created_at: :desc).map do |c|
@_clients ||= current_company.clients.kept.order(created_at: :desc).map do |c|
c.attributes.merge({ hours_logged: c.timesheet_entries.sum(:duration) })
end
end
Expand Down
9 changes: 0 additions & 9 deletions app/controllers/concerns/current_company_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,5 @@ def current_company
return if current_user.nil?

@_current_company ||= current_user&.current_workspace || current_user.companies.first

# TODO: Once switch workspace feature is added the logic to set Current workspace for user will be moved to
# - Company#create action
# - Controller action that will Switch a users' workspace
if current_user.current_workspace_id? && @_current_company && current_user.current_workspace_id != @_current_company.id
current_user.update(current_workspace_id: @_current_company.id)
end

@_current_company
end
end
20 changes: 19 additions & 1 deletion app/controllers/concerns/error_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ module ErrorHandler
extend ActiveSupport::Concern

included do
rescue_from ActionController::RoutingError, with: :handle_not_found_error
rescue_from ActionController::RoutingError, ActiveRecord::RecordNotFound, with: :handle_not_found_error
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
rescue_from Discard::RecordNotDiscarded, with: :record_not_discarded
rescue_from ActiveRecord::RecordInvalid, with: :record_invalid
end

private
Expand Down Expand Up @@ -38,4 +40,20 @@ def user_not_authorized(exception)
format.json { render json: { errors: message }, status: :forbidden }
end
end

def record_not_discarded(exception)
message = exception.message

respond_to do |format|
format.json { render json: { errors: message, notice: I18n.t("errors.internal_server_error") }, status: :internal_server_error }
format.html { render file: "public/500.html", status: :internal_server_error, layout: false, alert: message }
end
end

def record_invalid(exception)
respond_to do |format|
format.json { render json: { errors: exception.record.errors, notice: I18n.t("client.update.failure.message") }, status: :unprocessable_entity }
format.html { render file: "public/422.html", status: :unprocessable_entity, layout: false, alert: message }
end
end
end
21 changes: 11 additions & 10 deletions app/controllers/internal_api/v1/clients_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,24 @@
class InternalApi::V1::ClientsController < InternalApi::V1::ApplicationController
def update
authorize client
unless current_company.id == client.company_id
return render json: {
message: I18n.t("client.update.failure.unauthorized")
}, status: :forbidden
end

if client.update(client_params)
if client.update!(client_params)
render json: {
success: true,
client: client,
notice: I18n.t("client.update.success.message")
}, status: :ok
else
end
end

def destroy
authorize client

if client.discard!
render json: {
errors: client.errors,
notice: I18n.t("client.update.failure.message")
}, status: :unprocessable_entity
client: client,
notice: I18n.t("client.delete.success.message")
}, status: :ok
end
end

Expand Down
17 changes: 17 additions & 0 deletions app/controllers/internal_api/v1/reports_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

class InternalApi::V1::ReportsController < InternalApi::V1::ApplicationController
include Timesheet

def index
authorize :report
render json: { entries: entries }, status: :ok
end

private
def entries
current_company.timesheet_entries.map do |timesheet_entry|
timesheet_entry.formatted_entry.transform_keys { |key| key.to_s.camelize(:lower) }
end
end
end
43 changes: 19 additions & 24 deletions app/controllers/internal_api/v1/timesheet_entry_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,44 @@
class InternalApi::V1::TimesheetEntryController < InternalApi::V1::ApplicationController
include Timesheet

skip_after_action :verify_authorized, only: [:index]
after_action :verify_policy_scoped, only: [:index]

def index
timesheet_entries = current_user.timesheet_entries.during(params[:from], params[:to])
timesheet_entries = policy_scope(TimesheetEntry)
timesheet_entries = timesheet_entries.where(user_id: params[:user_id] || current_user.id).during(params[:from], params[:to])
entries = formatted_entries_by_date(timesheet_entries)
render json: { success: true, entries: entries }
render json: { entries: entries }
end

def create
timesheet_entry = project.timesheet_entries.new(timesheet_entry_params)
authorize TimesheetEntry
timesheet_entry = current_project.timesheet_entries.new(timesheet_entry_params)
timesheet_entry.user = current_user
if timesheet_entry.save
render json: { success: true, entry: timesheet_entry.formatted_entry }
else
render json: timesheet_entry.errors, status: :unprocessable_entity
end
render json: { notice: I18n.t("timesheet_entry.create.message"), entry: timesheet_entry.formatted_entry } if timesheet_entry.save
end

def update
timesheet_entry.project = project
if timesheet_entry.update(timesheet_entry_params)
render json: { success: true, entry: timesheet_entry.formatted_entry }
else
render json: timesheet_entry.errors, status: :unprocessable_entity
end
authorize current_timesheet_entry
current_timesheet_entry.project = current_project
render json: { notice: I18n.t("timesheet_entry.update.message"), entry: current_timesheet_entry.formatted_entry }, status: :ok if current_timesheet_entry.update(timesheet_entry_params)
end

def destroy
if timesheet_entry.destroy
render json: { success: true }
else
render json: timesheet_entry.errors, status: :unprocessable_entity
end
authorize current_timesheet_entry
render json: { notice: I18n.t("timesheet_entry.destroy.message") } if current_timesheet_entry.destroy
end

private
def project
project ||= Project.find_by!(name: params[:project_name])
def current_project
@_current_project ||= current_company.projects.find(params[:project_id])
end

def timesheet_entry
timesheet_entry ||= TimesheetEntry.find(params[:id])
def current_timesheet_entry
@_current_timesheet_entry ||= current_user.timesheet_entries.find(params[:id])
end

def timesheet_entry_params
params.require(:timesheet_entry).permit(:project_id, :duration, :work_date, :note)
params.require(:timesheet_entry).permit(:project_id, :duration, :work_date, :note, :bill_status)
end
end
21 changes: 21 additions & 0 deletions app/controllers/internal_api/v1/workspaces_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

class InternalApi::V1::WorkspacesController < ApplicationController
skip_after_action :verify_authorized

def update
workspace = current_user.companies.find(params[:id])
if current_user.update(current_workspace_id: workspace.id)
render json: {
success: true,
workspace: workspace,
notice: I18n.t("workspaces.update.success")
}, status: :ok
else
render json: {
errors: current_user.errors,
notice: I18n.t("workspaces.update.failure")
}, status: :unprocessable_entity
end
end
end
7 changes: 7 additions & 0 deletions app/controllers/reports_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class ReportsController < ApplicationController
def index
authorize :report
end
end
16 changes: 8 additions & 8 deletions app/controllers/time_tracking_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ class TimeTrackingController < ApplicationController
skip_after_action :verify_authorized

def index
@is_admin = current_user.has_owner_or_admin_role?(current_company)
@clients = current_company.clients.includes(:projects)
@projects = {}
@clients.map do |c|
@projects[c.name] = c.projects
end
is_admin = current_user.is_admin?
clients = current_company.clients.includes(:projects)
projects = {}
clients.map { |client| projects[client.name] = client.projects }

timesheet_entries = current_user.timesheet_entries.during(
timesheet_entries = current_user.timesheet_entries.in_workspace(current_company).during(
Date.today.beginning_of_week,
Date.today.end_of_week
)
@entries = formatted_entries_by_date(timesheet_entries)
entries = formatted_entries_by_date(timesheet_entries)

render :index, locals: { is_admin: is_admin, clients: clients, projects: projects, entries: entries }
end
end
Loading

0 comments on commit ca944be

Please sign in to comment.