Compare commits

...

4 Commits

Author SHA1 Message Date
bilal
43e69d1e88 change text and spec 2020-06-22 19:22:23 +02:00
bilal
9f4cb16016 update notice text when creating task request 2020-06-19 12:36:16 +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
23 changed files with 349 additions and 101 deletions

View File

@@ -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

@@ -13,17 +13,19 @@ class TaskRequestsController < ApplicationController
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
@@ -48,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

@@ -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

@@ -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

@@ -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

@@ -1,18 +1,49 @@
<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| %>
<%= link_to file.filename, rails_blob_path(file, disposition: 'attachment'), class: "btn btn-link" %><br/>
<% end %>
<% else %>
No files attached
<% end %>
</dd>
</dl>
<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, :taskme) %>
<%= product_wordmark :task_me, class: class_string("d-inline-block", "disabled" => !Current.account.taskme_enabled?) %>
<% end %>
</li>
</ul>
</nav>
<hr class="divider-light mx-n4">

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 %>
@@ -24,11 +29,6 @@
data-placeholder="<%= dropzone_placeholder_message_for(task_request) %>"
data-submit-button="#submit_folder"></div>
<% end %>
<div class="alert alert-info text-center text-md-left mt-4">
<%= fa_icon "info-circle" %>
<strong>After you submit this information you will immediately be connected with a BIG representative who will be able to collect any additional information needed, answer your questions, etc.</strong>
</div>
<div class="row align-items-center text-center mt-4">
<%= link_to t("shared.cancel"), [project, :task_requests], class: "col-3 text-reset" %>

View File

@@ -0,0 +1,4 @@
<% if params[:show_chat] %>
<%= javascript_include_tag "https://js.hs-scripts.com/7344617.js", defer: "defer", async: true, id: "hs-script-loader" %>
<% end %>
<p class="alert alert-success p-3 lead text-center"><%= t '.success_message' %></p>

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

@@ -12,6 +12,6 @@
<%= task.status.titleize %>
</td>
<td>
<%= task.deliverable_url %>
<%= link_to "View Deliverable", task.deliverable_url, target: "_blank" %>
</td>
</tr>

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:
@@ -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
@@ -956,6 +967,8 @@ en:
task_request_time_allowed: Time Allowed
new:
heading: New Task Request
show:
empty: Attached files will appear here.
task_request:
actions:
manage: Manage

View File

@@ -183,7 +183,11 @@ es:
guardian_photo:
heading: Guardian Photo (ES)
task_requests:
form:
info_message: After submitting this task request, you'll be connected via chat with a ME Suite representative. (ES)
task_request:
actions:
manage: Manage (ES)
open_deliverable: Open Deliverable (ES)
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)

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

@@ -24,7 +24,7 @@ RSpec.describe TasksController, type: :controller do
get :index, params: { project_id: project }
expect(response.body).to have_content "Completed"
expect(response.body).to have_content "example.com/deliverables"
expect(response.body).to have_link "View Deliverable"
end
context "when there are many records" do

View File

@@ -1,6 +1,7 @@
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"

View File

@@ -24,12 +24,21 @@ feature "Admin managing task requests" do
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
@@ -44,7 +53,7 @@ feature "Admin managing task requests" do
expect(page).to have_content 'Files'
task_request.files.each do |file|
expect(page).to have_link file.blob.filename
expect(page).to have_content file.blob.filename
end
end
@@ -56,7 +65,7 @@ feature "Admin managing task requests" do
click_link 'View'
switch_to_window(windows.last)
expect(page).to have_content 'No files attached'
expect(page).to have_content 'Attached files will appear here.'
end
scenario "task requests table is visible" do

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,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