Compare commits

..

7 Commits

Author SHA1 Message Date
Bilal
e8a311fdea sort translations 2020-06-24 14:43:20 +02:00
Bilal
ba826508d8 add description column to the task requests table 2020-06-24 14:23:26 +02:00
Bilal
a5213feccc sync 2020-06-24 13:21:12 +02:00
Senad Uka
c167889ea3 Upstream sync task me mvp 2020-06-24 04:49:28 +02:00
Senad Uka
3e917c29f0 task me sync 2020-06-19 12:32:50 +02:00
Senad Uka
8ad89371b8 Task mvp upstream sync 2020-06-15 11:02:00 +02:00
Senad Uka
9d7e2c044a Upstream sync task me 2020-06-09 06:34:58 +02:00
36 changed files with 692 additions and 102 deletions

View File

@@ -14,6 +14,7 @@ $red: #F9002B;
$green: #51B61B;
$teal: #32C498;
$purple: #5139EE;
$yellow: #F9BE1B;
$dark: $gray-900;
$success: $teal;
$link-color: $body-color;

View File

@@ -32,14 +32,14 @@
&.release-me {
span:last-child {
background-color: $teal;
color: $body-color;
color: $white;
}
}
&.direct-me {
span:last-child {
background-color: $green;
color: $body-color;
color: $white;
}
}
@@ -53,7 +53,14 @@
&.deliver-me {
span:last-child {
background-color: $purple;
color: white;
color: $white;
}
}
&.task-me {
span:last-child {
background-color: $yellow;
color: $white;
}
}

View File

@@ -1,5 +1,5 @@
class Admin::TaskRequestsController < Admin::ApplicationController
before_action :set_task_request, only: [:edit, :update]
before_action :set_task_request, only: [:edit, :update, :show]
def index
@task_requests = task_requests.order_by_recent.paginate(page: params[:page])
@@ -8,6 +8,10 @@ class Admin::TaskRequestsController < Admin::ApplicationController
def edit
end
def show
@files = @task_request.files.paginate(page: params[:page])
end
def update
if @task_request.update(task_request_params)
redirect_to [:admin, :task_requests], notice: t(".notice")

View File

@@ -6,28 +6,26 @@ class TaskRequestsController < ApplicationController
before_action :set_task_request, only: [:show, :edit, :update, :cancel]
def index
if params[:completed_only]
@task_requests = task_requests.completed.order_by_recent.paginate(page: params[:page])
else
@task_requests = task_requests.order_by_recent.paginate(page: params[:page])
end
@task_requests = task_requests.order_by_recent.paginate(page: params[:page])
end
def new
end
def create
@task_request.attributes = task_request_params
@task_request.attributes = task_request_params_with_email
if @task_request.save
log_create_analytics
redirect_to [@project, :task_requests], notice: t(".notice")
taskme_url = url_for([:admin, @task_request])
SubmitHubspotTaskRequestFormJob.perform_later(@task_request.user_email, taskme_url)
else
render :new
end
end
def show
@files = @task_request.files.paginate(page: params[:page])
end
def edit
@@ -52,6 +50,10 @@ class TaskRequestsController < ApplicationController
params.require(:task_request).permit(:description, :deadline, :time_allowed, :additional_notes, files: [])
end
def task_request_params_with_email
task_request_params.merge(user_email: Current.user.email)
end
def set_project
@project = policy_scope(Project).find(params[:project_id])
end

View File

@@ -0,0 +1,19 @@
class TasksController < ApplicationController
before_action :set_project
include ProjectLayout
def index
@tasks = task_requests.completed.order_by_recent.paginate(page: params[:page])
end
private
def set_project
@project = policy_scope(Project).find(params[:project_id])
end
def task_requests
authorize policy_scope(@project.task_requests)
end
end

View File

@@ -7,8 +7,8 @@ module DescriptionListHelper
safe_join(tags)
end
def description_list_pair_for(record, attribute, append: nil)
term = translation_for(record, attribute)
def description_list_pair_for(record, attribute, append: nil, custom_label: nil)
term = custom_label.nil? ? translation_for(record, attribute) : custom_label
definition = record.send(attribute)
description_list_pair(term, definition, append: append)

View File

@@ -7,6 +7,8 @@ module DropzoneHelper
"To Add Audio Files to the release:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse files"
when "directory"
"To Add Files to the Folder:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse files"
when "task_request"
"To Add Files for the Task:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse files"
else
"To Add Photos to the release:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse photos and connect to Camera"
end

View File

@@ -1,5 +1,6 @@
$(document).on("turbolinks:load", () => {
$('.datepicker-control').datepicker({
format: "yyyy-mm-dd"
format: "yyyy-mm-dd",
todayHighlight: true
});
});

View File

@@ -0,0 +1,18 @@
class SubmitHubspotTaskRequestFormJob < ApplicationJob
queue_as :default
def perform(user_email, taskme_url)
hubspot_task_request_form_guid = ENV["HUBSPOT_TASK_REQUEST_FORM_GUID"]
return unless hubspot_task_request_form_guid.present?
submission_params = {
email: user_email,
taskme_url: taskme_url
}
form = Hubspot::Form.new("guid" => hubspot_task_request_form_guid)
is_form_sumitted = form.submit(submission_params)
raise StandardError.new "Failed to submit the task request hubspot form data: #{is_form_sumitted}" unless is_form_sumitted
end
end

View File

@@ -79,8 +79,8 @@ class Account < ApplicationRecord
plan_uid.to_s == "me_suite" || plan_uid.to_s == "releaseme"
end
def assistme_enabled?
plan_uid.to_s == "me_suite" || plan_uid.to_s == "assistme"
def taskme_enabled?
plan_uid.to_s == "me_suite" || plan_uid.to_s == "taskme"
end
def plan_name
@@ -91,8 +91,8 @@ class Account < ApplicationRecord
"DirectME"
when "releaseme"
"ReleaseME"
when "assistme"
"AssistME"
when "taskme"
"TaskME"
when "me_suite"
"ME Suite"
end

View File

@@ -22,4 +22,8 @@ class TaskRequestPolicy < ApplicationPolicy
def cancel?
true
end
def open_deliverable?
true
end
end

View File

@@ -1,7 +1,7 @@
<%= errors_summary_for task_request %>
<%= bootstrap_form_with model: model, local: true do |form| %>
<%= form.select :status, options_for_select(TaskRequest.statuses.except(:cancelled).keys, task_request.status), { class: "form-control" } %>
<%= form.select :status, options_for_select(TaskRequest.statuses.except(:cancelled).keys, task_request.status), {}, class: "form-control custom-select" %>
<%= form.text_field :deliverable_url %>
<div class="row align-items-center text-center mt-4">

View File

@@ -24,6 +24,7 @@
<div class="btn-group">
<%= button_tag "Manage", class: "btn btn-light btn-sm dropdown-toggle border", data: { toggle: "dropdown", boundary: "window" }, aria: { haspopup: true, expanded: false } %>
<div class="dropdown-menu dropdown-menu-right">
<%= link_to fa_icon("tasks", text: "View"), [:admin, task_request], class: "dropdown-item", target: '_blank' %>
<%= link_to fa_icon("pencil", text: "Edit"), [:edit, :admin, task_request], class: "dropdown-item" %>
</div>
</div>

View File

@@ -0,0 +1,49 @@
<div class="card shadow-sm">
<%= card_header text: "Task Details", close_action_path: [:admin, :task_requests] %>
<div class="card-body">
<div class="row">
<div class="col-md-6 col-sm-12">
<dl>
<%= description_list_pair_for @task_request.project.account, :name, custom_label: "Account Name", append: ":" %>
<%= description_list_pair_for @task_request.project, :name, custom_label: "Project Name", append: ":" %>
<%= description_list_pair_for @task_request, :created_at, append: ":" %>
<%= description_list_pair_for @task_request, :user_email, append: ":" %>
<%= description_list_pair_for @task_request, :status, append: ":" %>
</dl>
</div>
<div class="col-md-6 col-sm-12">
<dl>
<%= description_list_pair_for @task_request, :deadline, append: ":" %>
<%= description_list_pair_for @task_request, :time_allowed, append: ":" %>
<%= description_list_pair_for @task_request, :description, append: ":" %>
<%= description_list_pair_for @task_request, :additional_notes, append: ":" %>
</dl>
</div>
<div class="col-md-12">
<h2 class="h6 mt-3">Files:</h2>
<div class="pt-2 mx-n3">
<table class="table table-striped tr-px-4 align-all-middle">
<thead class="thead-light">
<tr>
<th>Filename</th>
<th></th>
</tr>
</thead>
<tbody id="task_requests">
<% if @files.any? %>
<%= render partial: "task_requests/file", collection: @files %>
<% else %>
<tr>
<td colspan="12" class="py-4 text-center text-muted"><%= t(".empty") %></td>
</tr>
<% end %>
</tbody>
</table>
<div class="mt-4" id="task_requests_pagiantion">
<%= will_paginate @files %>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -11,6 +11,12 @@
<hr class="divider-light mx-n4">
<nav>
<ul class="nav nav-pills nav-pills-dark flex-column">
<li class="nav-item">
<%= link_to [project, :task_requests], class: class_string("nav-link", "active" => controller_name == "task_requests") do %>
<%= lock_icon_for(Current.account, :taskme) %>
<%= product_wordmark :task_me, class: class_string("d-inline-block", "disabled" => !Current.account.taskme_enabled?) %>
<% end %>
</li>
<li class="nav-item">
<%= link_to [project, :contract_templates], class: class_string("nav-link", "active" => %w(contract_templates release_template_imports).include?(controller_name)) do %>
<%= lock_icon_for Current.account, :releaseme %>
@@ -35,12 +41,6 @@
<%= product_wordmark :deliver_me, class: class_string("d-inline-block", "disabled" => !Current.account.deliverme_enabled?) %>
<% end %>
</li>
<li class="nav-item">
<%= link_to [project, :task_requests], class: class_string("nav-link", "active" => controller_name == "task_requests") do %>
<%= lock_icon_for(Current.account, :assistme) %>
<%= product_wordmark :assist_me, class: class_string("d-inline-block", "disabled" => !Current.account.assistme_enabled?) %>
<% end %>
</li>
</ul>
</nav>
<hr class="divider-light mx-n4">

View File

@@ -18,7 +18,7 @@
<% end %>
<% if policy(Project).show_task_results? %>
<%= render "folder_card" do %>
<%= link_to t("projects.show.task_requests"), [@project, :task_requests, completed_only: true], class: "text-decoration-none text-reset stretched-link" %>
<%= link_to t("projects.show.tasks"), [@project, :tasks], class: "text-decoration-none text-reset stretched-link" %>
<% end %>
<% end %>
</div>

View File

@@ -0,0 +1,6 @@
<tr>
<td><%= file.filename %></td>
<td class="text-right">
<%= link_to fa_icon("download"), file, target: "_blank" %>
</td>
</tr>

View File

@@ -1,11 +1,16 @@
<%= errors_summary_for task_request %>
<%= bootstrap_form_with model: model, local: true do |form| %>
<%= form.text_area :description %>
<%= form.text_field :deadline, class: "datepicker-control" %>
<%= form.text_field :time_allowed %>
<%= form.text_area :additional_notes %>
<%= field_set_tag content_tag(:span, "Files", class: "h6 text-muted text-uppercase") do %>
<%= bootstrap_form_with model: model, url: [@project, @task_request, show_chat: true], local: true do |form| %>
<div class="alert alert-notice text-center pl-0 text-md-left mt-4">
<%= fa_icon "info-circle" %>
<strong><%= t '.info_message' %></strong>
</div>
<%= form.text_area :description, label: t('.labels.description') %>
<%= form.text_field :deadline, class: "datepicker-control", label: t('.labels.deadline') %>
<%= form.text_field :time_allowed, label: t('.labels.time_allowed') %>
<%= form.text_area :additional_notes, label: t('.labels.additional_notes') %>
<%= field_set_tag content_tag(:span, t('.labels.files'), class: "h6 text-muted text-uppercase") do %>
<div class="field d-none">
<%= form.label :files %>
<%= form.file_field :files, disable: true, direct_upload: true, multiple: true, id: "task_request_files", hide_label: true %>

View File

@@ -5,17 +5,24 @@
<td>
<%= task_request.deadline.try(:strftime, '%D') %>
</td>
<td>
<%= truncate(task_request.description) {
link_to t('.actions.read_more'),
'#',
class: 'alert-link',
data: {
toggle: "popover",
content: task_request.description,
trigger: "hover"
}
} %>
</td>
<td>
<%= task_request.time_allowed %>
</td>
<td>
<%= task_request.status.titleize %>
</td>
<% if params[:completed_only] %>
<td>
<%= task_request.deliverable_url %>
</td>
<% end %>
<td class="text-right">
<div class="btn-group">
<%= button_tag t(".actions.manage"), class: "btn btn-light btn-sm dropdown-toggle border", data: { toggle: "dropdown", boundary: "window" }, aria: { haspopup: true, expanded: false } %>
@@ -26,6 +33,9 @@
<% if policy(task_request).edit? %>
<%= link_to fa_icon("pencil fw", text: "Edit"), [:edit, task_request.project, task_request], class: "dropdown-item" %>
<% end %>
<% if policy(task_request).open_deliverable? && task_request.status == "completed" %>
<%= link_to fa_icon("external-link fw", text: t(".actions.open_deliverable")), task_request.deliverable_url, class: "dropdown-item", target: '_blank' %>
<% end %>
<% if policy(task_request).cancel? && !task_request.cancelled? %>
<%= link_to fa_icon("ban fw", text: "Cancel"), [:cancel, task_request.project, task_request], class: "dropdown-item", method: :post %>
<% end %>

View File

@@ -0,0 +1,9 @@
<% if params[:show_chat] %>
<%= javascript_include_tag "https://js.hs-scripts.com/7344617.js", defer: "defer", async: true, id: "hs-script-loader" %>
<%= javascript_tag nonce: true do %>
$(document).ready(function(){
window.HubSpotConversations.widget.open();
});
<% end %>
<% end %>
<p class="alert alert-success p-3 lead text-center"><%= t '.success_message' %></p>

View File

@@ -1,4 +1,4 @@
<%= product_wordmark :assist_me, class: "small mb-3" %>
<%= product_wordmark :task_me, class: "small mb-3" %>
<div class="row">
<div class="col-md-12">
@@ -16,11 +16,9 @@
<tr>
<th><%= t(".table_headers.task_request_created_on") %></th>
<th><%= t(".table_headers.task_request_deadline") %></th>
<th><%= t(".table_headers.task_request_description") %></th>
<th><%= t(".table_headers.task_request_time_allowed") %></th>
<th><%= t(".table_headers.task_request_status") %></th>
<% if params[:completed_only] %>
<th><%= t(".table_headers.task_request_results") %></th>
<% end %>
<th></th>
</tr>
</thead>
@@ -29,7 +27,7 @@
<%= render @task_requests %>
<% else %>
<tr>
<td colspan="5" class="py-4 text-center text-muted"><%= t(".empty") %></td>
<td colspan="20" class="py-4 text-center text-muted"><%= t(".empty") %></td>
</tr>
<% end %>
</tbody>

View File

@@ -1,18 +1,46 @@
<dl>
<%= description_list_pair_for @task_request, :description, append: ":" %>
<%= description_list_pair_for @task_request, :created_at, append: ":" %>
<%= description_list_pair_for @task_request, :deadline, append: ":" %>
<%= description_list_pair_for @task_request, :time_allowed, append: ":" %>
<%= description_list_pair_for @task_request, :additional_notes, append: ":" %>
<%= description_list_pair_for @task_request, :status, append: ":" %>
<dt>Files:</dt>
<dd>
<% if @task_request.files.present? %>
<% @task_request.files.each do |file| %>
<%= file.filename %><br>
<% end %>
<% else %>
"No files attached."
<% end %>
</dd>
</dl>
<div class="card shadow-sm">
<%= card_header text: "Task Details", close_action_path: [@project, :task_requests] %>
<div class="card-body">
<div class="row">
<div class="col-md-6 col-sm-12">
<dl>
<%= description_list_pair_for @task_request, :description, append: ":" %>
<%= description_list_pair_for @task_request, :created_at, append: ":" %>
<%= description_list_pair_for @task_request, :status, append: ":" %>
</dl>
</div>
<div class="col-md-6 col-sm-12">
<dl>
<%= description_list_pair_for @task_request, :deadline, append: ":" %>
<%= description_list_pair_for @task_request, :time_allowed, append: ":" %>
<%= description_list_pair_for @task_request, :additional_notes, append: ":" %>
</dl>
</div>
<div class="col-md-12">
<h2 class="h6 mt-3">Files:</h2>
<div class="pt-2 mx-n3">
<table class="table table-striped tr-px-4 align-all-middle">
<thead class="thead-light">
<tr>
<th>Filename</th>
<th></th>
</tr>
</thead>
<tbody id="task_requests">
<% if @files.any? %>
<%= render partial: "file", collection: @files %>
<% else %>
<tr>
<td colspan="12" class="py-4 text-center text-muted"><%= t(".empty") %></td>
</tr>
<% end %>
</tbody>
</table>
<div class="mt-4" id="task_requests_pagiantion">
<%= will_paginate @files %>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,17 @@
<tr>
<td>
<%= task.created_at.strftime('%D') %>
</td>
<td>
<%= task.deadline.try(:strftime, '%D') %>
</td>
<td>
<%= task.time_allowed %>
</td>
<td>
<%= task.status.titleize %>
</td>
<td>
<%= link_to "View Deliverable", task.deliverable_url, target: "_blank" %>
</td>
</tr>

View File

@@ -0,0 +1,26 @@
<div class="border bg-white rounded shadow-sm pb-3 table-responsive">
<table class="table table-striped tr-px-4 align-all-middle">
<thead class="thead-light">
<tr>
<th><%= t(".table_headers.task_request_created_on") %></th>
<th><%= t(".table_headers.task_request_deadline") %></th>
<th><%= t(".table_headers.task_request_time_allowed") %></th>
<th><%= t(".table_headers.task_request_status") %></th>
<th><%= t(".table_headers.task_request_results") %></th>
</tr>
</thead>
<tbody id="task_requests">
<% if @tasks.any? %>
<%= render partial: "task", collection: @tasks %>
<% else %>
<tr>
<td colspan="5" class="py-4 text-center text-muted"><%= t(".empty") %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
<div id="task_requests_pagination" class="mt-3">
<%= will_paginate @tasks %>
</div>

View File

@@ -96,6 +96,8 @@ en:
task_requests:
index:
empty: Task requests will appear here
show:
empty: Attached files will appear here.
update:
notice: The task request has been updated successfully
users:
@@ -734,7 +736,7 @@ en:
music_release: Music Releases (%{count})
report: Reports
talent_release: Talent Releases (%{count})
task_requests: Tasks
tasks: Tasks
public:
acquired_media_releases:
new:
@@ -875,7 +877,6 @@ en:
title: Sign In
shared:
ago: ago
assist_me: Assist
back: Back
cancel: Cancel
clear: Clear
@@ -901,6 +902,7 @@ en:
tag_multiple_releases: Add Tag
tag_multiple_releases_form:
submit: Add
task_me: Task
tags:
form:
submit: Add
@@ -941,9 +943,18 @@ en:
notice: Task has been cancelled successfully.
create:
notice: Task request created succussfully.
success_message: Your task request was successfully submitted. Thank you. A chat window will pop up on the lower right in a few seconds.
edit:
heading:
Edit Task Request
form:
info_message: After submitting this task request, you'll be connected via chat with a ME Suite representative.
labels:
additional_notes: Please add any additional notes we should be aware of regarding this task.
deadline: What is the deadline for this task?
description: Please describe the task.
files: Please attach any files related to this task
time_allowed: How many hours would like spend on this task?
index:
actions:
new: Create Task Request
@@ -951,16 +962,30 @@ en:
table_headers:
task_request_created_on: Created On
task_request_deadline: Deadline
task_request_description: Description
task_request_results: Task Results
task_request_status: Status
task_request_time_allowed: Time Allowed
new:
heading: New Task Request
show:
empty: Attached files will appear here.
task_request:
actions:
manage: Manage
open_deliverable: Open Deliverable
read_more: read more
update:
notice: Task request updated successfully.
tasks:
index:
empty: Tasks will appear here.
table_headers:
task_request_created_on: Created On
task_request_deadline: Deadline
task_request_results: Task Results
task_request_status: Status
task_request_time_allowed: Time Allowed
user_mailer:
existing_account:
subject: You've been added as a ME Suite Account Manager

View File

@@ -182,3 +182,16 @@ es:
photos:
guardian_photo:
heading: Guardian Photo (ES)
task_requests:
create:
success_message: Your task request was successfully submitted. Thank you. A chat window will pop up on the lower right in a few seconds. (ES)
form:
info_message: After submitting this task request, you'll be connected via chat with a ME Suite representative. (ES)
index:
table_headers:
task_request_description: Description (ES)
task_request:
actions:
manage: Manage (ES)
open_deliverable: Open Deliverable (ES)
read_more: read more (ES)

View File

@@ -31,7 +31,7 @@ Rails.application.routes.draw do
resources :users, only: [:index, :new, :create, :edit, :update, :destroy] do
resource :masquerade, only: :create
end
resources :task_requests, only: [:index, :edit, :update]
resources :task_requests, only: [:index, :edit, :update, :show]
root to: "accounts#index", as: :signed_in_root
end
@@ -103,6 +103,7 @@ Rails.application.routes.draw do
post :cancel
end
end
resources :tasks, only: :index
end
resource :profile, only: [:show, :update]
resources :videos, only: [] do

View File

@@ -0,0 +1,5 @@
class AddUserEmailToTaskRequests < ActiveRecord::Migration[6.0]
def change
add_column :task_requests, :user_email, :string
end
end

View File

@@ -37,20 +37,20 @@ CREATE EXTENSION IF NOT EXISTS pg_trgm WITH SCHEMA public;
COMMENT ON EXTENSION pg_trgm IS 'text similarity measurement and index searching based on trigrams';
--
-- Name: pg_search_dmetaphone(text); Type: FUNCTION; Schema: public; Owner: -
--
CREATE FUNCTION public.pg_search_dmetaphone(text) RETURNS text
LANGUAGE sql IMMUTABLE STRICT
AS $_$
SELECT array_to_string(ARRAY(SELECT dmetaphone(unnest(regexp_split_to_array($1, E'\\s+')))), ' ')
$_$;
--
-- Name: pg_search_dmetaphone(text); Type: FUNCTION; Schema: public; Owner: -
--
CREATE FUNCTION public.pg_search_dmetaphone(text) RETURNS text
LANGUAGE sql IMMUTABLE STRICT
AS $_$
SELECT array_to_string(ARRAY(SELECT dmetaphone(unnest(regexp_split_to_array($1, E'\\s+')))), ' ')
$_$;
SET default_tablespace = '';
SET default_table_access_method = heap;
SET default_with_oids = false;
--
-- Name: account_auths; Type: TABLE; Schema: public; Owner: -
@@ -615,15 +615,6 @@ CREATE SEQUENCE public.contract_templates_id_seq
ALTER SEQUENCE public.contract_templates_id_seq OWNED BY public.contract_templates.id;
--
-- Name: data_migrations; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.data_migrations (
version character varying NOT NULL
);
--
-- Name: directories; Type: TABLE; Schema: public; Owner: -
--
@@ -1181,6 +1172,7 @@ CREATE TABLE public.settings (
--
CREATE SEQUENCE public.settings_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
@@ -1216,6 +1208,7 @@ CREATE TABLE public.taggings (
--
CREATE SEQUENCE public.taggings_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
@@ -1246,6 +1239,7 @@ CREATE TABLE public.tags (
--
CREATE SEQUENCE public.tags_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
@@ -1340,7 +1334,8 @@ CREATE TABLE public.task_requests (
status integer DEFAULT 0,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL,
deliverable_url character varying
deliverable_url character varying,
user_email character varying
);
@@ -1596,9 +1591,9 @@ CREATE TABLE public.zoom_meetings (
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL,
broadcast_id bigint,
status integer DEFAULT 0,
zoom_user_id bigint,
project_id bigint
project_id bigint,
status integer DEFAULT 0
);
@@ -2052,14 +2047,6 @@ ALTER TABLE ONLY public.contract_templates
ADD CONSTRAINT contract_templates_pkey PRIMARY KEY (id);
--
-- Name: data_migrations data_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.data_migrations
ADD CONSTRAINT data_migrations_pkey PRIMARY KEY (version);
--
-- Name: directories directories_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
@@ -3560,4 +3547,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200507110804'),
('20200512161738'),
('20200518200245'),
('20200519191908');
('20200519191908'),
('20200610143327');

View File

@@ -49,13 +49,6 @@ RSpec.describe TaskRequestsController, type: :controller do
end
describe "#create" do
it "responds with a redirect" do
post :create, params: { project_id: project.id, task_request: task_request_params }
expect(response).to be_redirect
expect(flash.notice).not_to be_nil
end
it "does create a new record" do
expect {
post :create, params: { project_id: project.id, task_request: task_request_params }
@@ -67,6 +60,12 @@ RSpec.describe TaskRequestsController, type: :controller do
post :create, params: { project_id: project.id, task_request: task_request_params }
}.to have_enqueued_job(TrackAnalyticsJob).with(user, account, :track_create_task_request, user_agent: "Rails Testing", user_ip: "0.0.0.0")
end
it "submits data to hubspot form" do
expect {
post :create, params: { project_id: project.id, task_request: task_request_params }
}.to have_enqueued_job(SubmitHubspotTaskRequestFormJob)
end
end
describe "#update" do
@@ -118,7 +117,7 @@ RSpec.describe TaskRequestsController, type: :controller do
private
def task_request_params
attributes = attributes_for(:task_request).except(:status)
attributes = attributes_for(:task_request).except(:status, :user_email)
files = 2.times.map { Rack::Test::UploadedFile.new(file_fixture("location_photo.png"), "image/png") }
attributes.merge({ files: files })

View File

@@ -0,0 +1,40 @@
require 'rails_helper'
RSpec.describe TasksController, type: :controller do
render_views
let(:user) { create(:user) }
let(:account) { user.primary_account }
let(:project) { create(:project, account: user.primary_account) }
before do
sign_in user
end
describe "#index" do
it "responds successfully" do
get :index, params: { project_id: project }
expect(response).to be_successful
end
it "renders content" do
create(:task_request, :completed, project: project, description: "Another Request")
get :index, params: { project_id: project }
expect(response.body).to have_content "Completed"
expect(response.body).to have_link "View Deliverable"
end
context "when there are many records" do
it "paginates the table" do
create_list(:task_request, 20, :completed, project: project)
get :index, params: { project_id: project }
expect(response.body).to have_link("2", href: project_tasks_path(project, page: 2))
end
end
end
end

View File

@@ -1,11 +1,17 @@
FactoryBot.define do
factory :task_request do
association :project
user_email 'test@email.com'
deadline { 10.days.from_now }
time_allowed "10 days"
description "Task request"
additional_notes "Additional notes"
status 0
trait :completed do
deliverable_url "example.com/deliverables"
status 1
end
trait :with_files do
files { [Rack::Test::UploadedFile.new('spec/fixtures/files/contract.pdf', 'application/pdf')] }

View File

@@ -8,6 +8,66 @@ feature "Admin managing task requests" do
sign_in current_user
end
scenario "admin should see View action for task request in Manage dropdown", js: true do
create(:task_request)
visit admin_task_requests_path
click_on 'Manage'
expect(page).to have_content 'View'
end
scenario "admin can open detail view of task request", js: true do
task_request = create(:task_request, :with_files)
visit admin_task_requests_path
click_on 'Manage'
click_link 'View'
switch_to_window(windows.last)
expect(page).to have_content 'Account Name'
expect(page).to have_content task_request.project.account.name
expect(page).to have_content 'Project Name'
expect(page).to have_content task_request.project.name
expect(page).to have_content 'Description'
expect(page).to have_content task_request.description
expect(page).to have_content 'Created At'
expect(page).to have_content task_request.created_at
expect(page).to have_content 'User Email'
expect(page).to have_content task_request.user_email
expect(page).to have_content 'Deadline'
expect(page).to have_content task_request.deadline
expect(page).to have_content 'Time Allowed'
expect(page).to have_content task_request.time_allowed
expect(page).to have_content 'Additional Notes'
expect(page).to have_content task_request.additional_notes
expect(page).to have_content 'Status'
expect(page).to have_content task_request.status
expect(page).to have_content 'Files'
task_request.files.each do |file|
expect(page).to have_content file.blob.filename
end
end
scenario "no files attached label is shown if there are no files attached to the task request", js:true do
create(:task_request)
visit admin_task_requests_path
click_on 'Manage'
click_link 'View'
switch_to_window(windows.last)
expect(page).to have_content 'Attached files will appear here.'
end
scenario "task requests table is visible" do
visit admin_task_requests_path

View File

@@ -0,0 +1,92 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.feature 'User creates task request', type: :feature do
let(:current_user) { create(:user, :manager) }
let(:project) { create(:project, members: current_user, account: current_user.primary_account) }
before do
sign_in(current_user)
end
scenario 'creating a new task request' do
visit new_project_task_request_path(project)
fill_in description_field, with: 'Description of the task'
fill_in deadline_field, with: '2020-06-24'
fill_in time_allowed_field, with: '30'
fill_in additional_notes_field, with: 'Additional note about the task'
click_on 'Create Task request'
expect(page).to have_content task_created_message
end
scenario 'user can view task request details' do
create(:task_request, project: project, description: 'Description of the task', deadline: '2020-07-23', time_allowed: '10', additional_notes: 'Additional note about the task')
visit project_task_request_path(project, TaskRequest.first)
expect(page).to have_content('Description of the task')
expect(page).to have_content('2020-07-23')
expect(page).to have_content('10')
expect(page).to have_content('Additional note about the task')
end
scenario 'user can update existing task request' do
create(:task_request, project: project, description: 'Description of the task', deadline: '2020-08-23', time_allowed: '10', additional_notes: 'Additional note about the task')
visit edit_project_task_request_path(project, TaskRequest.first)
fill_in deadline_field, with: '2020-07-01'
fill_in time_allowed_field, with: '13'
click_on 'Update Task request'
expect(page).to have_content('13')
expect(page).to have_content('07/01/20')
end
scenario 'user can cancel a task request' do
create(:task_request, project: project, description: 'Description of the task', deadline: '2020-08-23', time_allowed: '10', additional_notes: 'Additional note about the task')
visit project_task_requests_path(project)
click_on 'Manage'
click_link 'Cancel'
expect(page).to have_content('Cancelled')
end
scenario 'user can view completed tasks' do
create_list(:task_request, 5, project: project, status: 'completed')
create_list(:task_request, 5, project: project, status: 'pending')
visit project_tasks_path(project)
expect(page).to have_content('Completed')
expect(page).not_to have_content('Pending')
end
private
def description_field
t "task_requests.form.labels.description"
end
def deadline_field
t "task_requests.form.labels.deadline"
end
def time_allowed_field
t "task_requests.form.labels.time_allowed"
end
def additional_notes_field
t "task_requests.form.labels.additional_notes"
end
def task_created_message
t 'task_requests.create.success_message'
end
end

View File

@@ -0,0 +1,116 @@
require "rails_helper"
feature "User managing task requests" do
let(:current_user) { create(:user) }
let(:project) { create(:project, account: current_user.primary_account) }
before :each do
sign_in current_user
end
scenario "task requests table is visible" do
visit project_task_requests_path(project)
expect(page).to have_content "Created On"
expect(page).to have_content "Deadline"
expect(page).to have_content description_column
expect(page).to have_content "Time Allowed"
expect(page).to have_content "Status"
end
scenario "sees list of task requests" do
visit project_task_requests_path(project)
expect(page).to have_content no_task_requests_label
task_request = create(:task_request, project: project)
visit project_task_requests_path(project)
expect(page).not_to have_content no_task_requests_label
expect(page).to have_content task_request.created_at.try(:strftime, '%D')
expect(page).to have_content task_request.deadline.try(:strftime, '%D')
expect(page).to have_content task_request.time_allowed
expect(page).to have_content task_request.status.capitalize
end
scenario "full description is shown if description text is not truncated" do
visit project_task_requests_path(project)
task_request = create(:task_request, project: project, description: 'Short Desc')
visit project_task_requests_path(project)
expect(page).to have_content task_request.description
end
scenario "truncated description is shown if description text is too long" do
visit project_task_requests_path(project)
task_request = create(:task_request,
project: project,
description: long_description_text)
visit project_task_requests_path(project)
expect(page).not_to have_content task_request.description
truncated_text = "#{task_request.description[0..26]}...read more"
expect(page).to have_content truncated_text
end
scenario "full description is shown when user hovers over read more link in description colum", js: true do
visit project_task_requests_path(project)
task_request = create(:task_request,
project: project,
description: long_description_text)
visit project_task_requests_path(project)
page.execute_script '$("a[data-toggle=popover]").trigger("mouseover")'
expect(page).to have_content task_request.description
end
scenario "user does not see open deliverable action in manage dropdown if task status is not completed" do
task_request = create(:task_request, project: project)
visit project_task_requests_path(project)
click_on manage_button
expect(page).not_to have_content open_deliverable_action_label
end
scenario "user can click deliverable action in manage dropdown if task status is completed", js: true do
create(:task_request, project: project, status: "completed", deliverable_url: "/")
visit project_task_requests_path(project)
click_on manage_button
expect(page).to have_content open_deliverable_action_label
click_link open_deliverable_action_label
switch_to_window(windows.last)
expect(page).to have_content add_new_project_label
end
private
def no_task_requests_label
"Task requests will appear here"
end
def manage_button
t "task_requests.task_request.actions.manage"
end
def open_deliverable_action_label
t "task_requests.task_request.actions.open_deliverable"
end
def add_new_project_label
t "projects.index.actions.new"
end
def description_column
t 'task_requests.index.table_headers.task_request_description'
end
def long_description_text
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
end
end

View File

@@ -0,0 +1,36 @@
require 'rails_helper'
RSpec.describe SubmitHubspotTaskRequestFormJob, type: :job do
describe '#perform_now' do
before do
ENV["HUBSPOT_TASK_REQUEST_FORM_GUID"] = "hubspot_task_request_form_guid"
end
it 'submits to the Hubspot API with the right params' do
form = double(:form)
allow(Hubspot::Form).to receive(:new).and_return(form)
allow(form).to receive(:submit).and_return(true)
SubmitHubspotTaskRequestFormJob.perform_now("email@test.com", "https://example.com/admin/task_requests/1")
expect(Hubspot::Form).to have_received(:new).with("guid" => "hubspot_task_request_form_guid")
expect(form).to have_received(:submit).with(
email: "email@test.com",
taskme_url: "https://example.com/admin/task_requests/1"
)
end
context 'when HUBSPOT_TASK_REQUEST_FORM_GUID is not available' do
it 'does not submit to the API' do
ENV["HUBSPOT_TASK_REQUEST_FORM_GUID"] = nil
form = double(:form)
allow(Hubspot::Form).to receive(:new).and_return(form)
allow(form).to receive(:submit)
SubmitHubspotTaskRequestFormJob.perform_now("email@test.com", "https://example.com/admin/task_requests/1")
expect(form).not_to have_received(:submit)
end
end
end
end