tudla_hubstaff 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +270 -0
- data/Rakefile +6 -0
- data/app/assets/stylesheets/tudla_hubstaff/application.css +15 -0
- data/app/assets/tailwind/tudla_hubstaff/engine.css +32 -0
- data/app/components/tudla_hubstaff/activity_row_component.html.erb +46 -0
- data/app/components/tudla_hubstaff/activity_row_component.rb +67 -0
- data/app/components/tudla_hubstaff/base_component.rb +10 -0
- data/app/components/tudla_hubstaff/project_row_component.html.erb +22 -0
- data/app/components/tudla_hubstaff/project_row_component.rb +21 -0
- data/app/components/tudla_hubstaff/task_activities_component.html.erb +82 -0
- data/app/components/tudla_hubstaff/task_activities_component.rb +93 -0
- data/app/components/tudla_hubstaff/task_row_component.html.erb +22 -0
- data/app/components/tudla_hubstaff/task_row_component.rb +17 -0
- data/app/components/tudla_hubstaff/ui/map_button_component.html.erb +8 -0
- data/app/components/tudla_hubstaff/ui/map_button_component.rb +21 -0
- data/app/components/tudla_hubstaff/ui/mapping_modal_component.html.erb +51 -0
- data/app/components/tudla_hubstaff/ui/mapping_modal_component.rb +34 -0
- data/app/components/tudla_hubstaff/ui/modal_component.html.erb +36 -0
- data/app/components/tudla_hubstaff/ui/modal_component.rb +17 -0
- data/app/components/tudla_hubstaff/ui/pagination_component.html.erb +19 -0
- data/app/components/tudla_hubstaff/ui/pagination_component.rb +47 -0
- data/app/components/tudla_hubstaff/ui/status_badge_component.html.erb +3 -0
- data/app/components/tudla_hubstaff/ui/status_badge_component.rb +26 -0
- data/app/components/tudla_hubstaff/ui/table_component.html.erb +20 -0
- data/app/components/tudla_hubstaff/ui/table_component.rb +15 -0
- data/app/components/tudla_hubstaff/ui.rb +4 -0
- data/app/components/tudla_hubstaff/user_activities_list_component.html.erb +70 -0
- data/app/components/tudla_hubstaff/user_activities_list_component.rb +92 -0
- data/app/components/tudla_hubstaff/user_row_component.html.erb +22 -0
- data/app/components/tudla_hubstaff/user_row_component.rb +13 -0
- data/app/controllers/tudla_hubstaff/activities_controller.rb +88 -0
- data/app/controllers/tudla_hubstaff/application_controller.rb +14 -0
- data/app/controllers/tudla_hubstaff/projects_controller.rb +75 -0
- data/app/controllers/tudla_hubstaff/tasks_controller.rb +75 -0
- data/app/controllers/tudla_hubstaff/users_controller.rb +75 -0
- data/app/helpers/tudla_hubstaff/application_helper.rb +4 -0
- data/app/javascript/tudla_hubstaff/application.js +21 -0
- data/app/javascript/tudla_hubstaff/controllers/activity_task_mapping_modal_controller.js +183 -0
- data/app/javascript/tudla_hubstaff/controllers/index.js +15 -0
- data/app/javascript/tudla_hubstaff/controllers/project_mapping_modal_controller.js +180 -0
- data/app/javascript/tudla_hubstaff/controllers/task_mapping_modal_controller.js +181 -0
- data/app/javascript/tudla_hubstaff/controllers/user_mapping_modal_controller.js +181 -0
- data/app/jobs/tudla_hubstaff/application_job.rb +4 -0
- data/app/jobs/tudla_hubstaff/fetch_updated_activities_job.rb +40 -0
- data/app/mailers/tudla_hubstaff/application_mailer.rb +6 -0
- data/app/models/tudla_hubstaff/activity.rb +6 -0
- data/app/models/tudla_hubstaff/application_record.rb +5 -0
- data/app/models/tudla_hubstaff/config.rb +8 -0
- data/app/models/tudla_hubstaff/organization_update.rb +5 -0
- data/app/models/tudla_hubstaff/project.rb +14 -0
- data/app/models/tudla_hubstaff/task.rb +9 -0
- data/app/models/tudla_hubstaff/user.rb +16 -0
- data/app/services/tudla_hubstaff/api_client.rb +64 -0
- data/app/services/tudla_hubstaff/api_connection.rb +54 -0
- data/app/services/tudla_hubstaff/concerns/activity_syncing.rb +46 -0
- data/app/services/tudla_hubstaff/concerns/task_syncing.rb +32 -0
- data/app/services/tudla_hubstaff/fetch_updated_activities_service.rb +28 -0
- data/app/services/tudla_hubstaff/get_task_service.rb +24 -0
- data/app/services/tudla_hubstaff/sync_activities_service.rb +28 -0
- data/app/services/tudla_hubstaff/sync_projects_service.rb +51 -0
- data/app/services/tudla_hubstaff/sync_tasks_service.rb +31 -0
- data/app/services/tudla_hubstaff/sync_users_service.rb +53 -0
- data/app/views/layouts/tudla_hubstaff/application.html.erb +19 -0
- data/app/views/tudla_hubstaff/projects/unmapped.html.erb +75 -0
- data/app/views/tudla_hubstaff/tasks/unmapped.html.erb +75 -0
- data/app/views/tudla_hubstaff/users/map_tudla_user.turbo_stream.erb +1 -0
- data/app/views/tudla_hubstaff/users/unmapped.html.erb +75 -0
- data/config/importmap.rb +7 -0
- data/config/routes.rb +41 -0
- data/db/migrate/20251230220607_create_tudla_hubstaff_users.rb +16 -0
- data/db/migrate/20251230222524_create_tudla_hubstaff_tasks.rb +21 -0
- data/db/migrate/20251230223731_create_tudla_hubstaff_projects.rb +15 -0
- data/db/migrate/20251230225408_add_hubstaff_ids_to_models.rb +14 -0
- data/db/migrate/20251231041753_add_last_updated_at_to_models.rb +7 -0
- data/db/migrate/20251231043338_add_tudla_ids_to_models.rb +14 -0
- data/db/migrate/20251231045209_create_tudla_hubstaff_activities.rb +30 -0
- data/db/migrate/20251231074018_create_tudla_hubstaff_configs.rb +15 -0
- data/db/migrate/20251231074556_create_tudla_hubstaff_organization_updates.rb +12 -0
- data/lib/generators/tudla_hubstaff/components_generator.rb +68 -0
- data/lib/generators/tudla_hubstaff/views_generator.rb +54 -0
- data/lib/tasks/tudla_hubstaff_tasks.rake +18 -0
- data/lib/tudla_hubstaff/engine.rb +88 -0
- data/lib/tudla_hubstaff/provider.rb +12 -0
- data/lib/tudla_hubstaff/version.rb +3 -0
- data/lib/tudla_hubstaff.rb +49 -0
- metadata +442 -0
data/config/importmap.rb
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
pin "@hotwired/stimulus", to: "stimulus.min.js"
|
|
2
|
+
pin "tudla_hubstaff/application", to: "tudla_hubstaff/application.js"
|
|
3
|
+
pin "tudla_hubstaff/controllers/index", to: "tudla_hubstaff/controllers/index.js"
|
|
4
|
+
pin "tudla_hubstaff/controllers/user_mapping_modal_controller", to: "tudla_hubstaff/controllers/user_mapping_modal_controller.js"
|
|
5
|
+
pin "tudla_hubstaff/controllers/task_mapping_modal_controller", to: "tudla_hubstaff/controllers/task_mapping_modal_controller.js"
|
|
6
|
+
pin "tudla_hubstaff/controllers/project_mapping_modal_controller", to: "tudla_hubstaff/controllers/project_mapping_modal_controller.js"
|
|
7
|
+
pin "tudla_hubstaff/controllers/activity_task_mapping_modal_controller", to: "tudla_hubstaff/controllers/activity_task_mapping_modal_controller.js"
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
TudlaHubstaff::Engine.routes.draw do
|
|
2
|
+
resources :users, only: [] do
|
|
3
|
+
collection do
|
|
4
|
+
get :unmapped
|
|
5
|
+
get :available_tudla_users
|
|
6
|
+
end
|
|
7
|
+
member do
|
|
8
|
+
patch :map_tudla_user
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
resources :tasks, only: [] do
|
|
13
|
+
collection do
|
|
14
|
+
get :unmapped
|
|
15
|
+
get :available_tudla_tasks
|
|
16
|
+
end
|
|
17
|
+
member do
|
|
18
|
+
patch :map_tudla_task
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
resources :projects, only: [] do
|
|
23
|
+
collection do
|
|
24
|
+
get :unmapped
|
|
25
|
+
get :available_tudla_projects
|
|
26
|
+
end
|
|
27
|
+
member do
|
|
28
|
+
patch :map_tudla_project
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
resources :activities, only: [] do
|
|
33
|
+
collection do
|
|
34
|
+
get :user_activities
|
|
35
|
+
get :available_tudla_tasks
|
|
36
|
+
end
|
|
37
|
+
member do
|
|
38
|
+
patch :map_activity_task
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class CreateTudlaHubstaffUsers < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :tudla_hubstaff_users do |t|
|
|
4
|
+
t.string :name, null: false
|
|
5
|
+
t.string :first_name, null: false
|
|
6
|
+
t.string :last_name, null: false
|
|
7
|
+
t.string :email
|
|
8
|
+
t.string :time_zone, null: false, default: "UTC"
|
|
9
|
+
t.string :ip_address
|
|
10
|
+
t.string :status, null: false, default: "active"
|
|
11
|
+
|
|
12
|
+
t.timestamps
|
|
13
|
+
end
|
|
14
|
+
add_index :tudla_hubstaff_users, :email, unique: true
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
class CreateTudlaHubstaffTasks < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :tudla_hubstaff_tasks do |t|
|
|
4
|
+
t.integer :integration_id
|
|
5
|
+
t.string :status
|
|
6
|
+
t.integer :project_id, null: false
|
|
7
|
+
t.string :project_type, null: false
|
|
8
|
+
t.string :summary, null: false
|
|
9
|
+
t.text :details
|
|
10
|
+
t.string :remote_id
|
|
11
|
+
t.string :remote_alternate_id
|
|
12
|
+
t.integer :lock_version
|
|
13
|
+
t.json :metadata, null: false, default: {}
|
|
14
|
+
t.datetime :completed_at
|
|
15
|
+
t.datetime :due_at
|
|
16
|
+
|
|
17
|
+
t.timestamps
|
|
18
|
+
end
|
|
19
|
+
add_index :tudla_hubstaff_tasks, :remote_id
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class CreateTudlaHubstaffProjects < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :tudla_hubstaff_projects do |t|
|
|
4
|
+
t.string :name, null: false
|
|
5
|
+
t.text :description
|
|
6
|
+
t.string :status
|
|
7
|
+
t.string :project_type, null: false
|
|
8
|
+
t.integer :client_id
|
|
9
|
+
t.json :metadata, null: false, default: {}
|
|
10
|
+
|
|
11
|
+
t.timestamps
|
|
12
|
+
end
|
|
13
|
+
add_index :tudla_hubstaff_projects, :client_id
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class AddHubstaffIdsToModels < ActiveRecord::Migration[8.1]
|
|
2
|
+
disable_ddl_transaction!
|
|
3
|
+
|
|
4
|
+
def change
|
|
5
|
+
add_column :tudla_hubstaff_users, :user_id, :bigint
|
|
6
|
+
add_index :tudla_hubstaff_users, :user_id, algorithm: :concurrently
|
|
7
|
+
|
|
8
|
+
add_column :tudla_hubstaff_projects, :project_id, :bigint
|
|
9
|
+
add_index :tudla_hubstaff_projects, :project_id, algorithm: :concurrently
|
|
10
|
+
|
|
11
|
+
add_column :tudla_hubstaff_tasks, :task_id, :bigint
|
|
12
|
+
add_index :tudla_hubstaff_tasks, :task_id, algorithm: :concurrently
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
class AddLastUpdatedAtToModels < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
add_column :tudla_hubstaff_users, :last_updated_at, :datetime
|
|
4
|
+
add_column :tudla_hubstaff_projects, :last_updated_at, :datetime
|
|
5
|
+
add_column :tudla_hubstaff_tasks, :last_updated_at, :datetime
|
|
6
|
+
end
|
|
7
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class AddTudlaIdsToModels < ActiveRecord::Migration[8.1]
|
|
2
|
+
disable_ddl_transaction!
|
|
3
|
+
|
|
4
|
+
def change
|
|
5
|
+
add_column :tudla_hubstaff_users, :tudla_user_id, :bigint
|
|
6
|
+
add_index :tudla_hubstaff_users, :tudla_user_id, algorithm: :concurrently
|
|
7
|
+
|
|
8
|
+
add_column :tudla_hubstaff_projects, :tudla_project_id, :bigint
|
|
9
|
+
add_index :tudla_hubstaff_projects, :tudla_project_id, algorithm: :concurrently
|
|
10
|
+
|
|
11
|
+
add_column :tudla_hubstaff_tasks, :tudla_task_id, :bigint
|
|
12
|
+
add_index :tudla_hubstaff_tasks, :tudla_task_id, algorithm: :concurrently
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
class CreateTudlaHubstaffActivities < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :tudla_hubstaff_activities do |t|
|
|
4
|
+
t.bigint :activity_id, null: false
|
|
5
|
+
t.string :date, null: false
|
|
6
|
+
t.bigint :user_id, null: false
|
|
7
|
+
t.bigint :project_id
|
|
8
|
+
t.bigint :task_id
|
|
9
|
+
t.integer :keyboard, default: 0
|
|
10
|
+
t.integer :mouse, default: 0
|
|
11
|
+
t.integer :overall, default: 0
|
|
12
|
+
t.integer :tracked, default: 0
|
|
13
|
+
t.integer :input_tracked, default: 0
|
|
14
|
+
t.integer :manual, default: 0
|
|
15
|
+
t.integer :idle, default: 0
|
|
16
|
+
t.integer :resumed, default: 0
|
|
17
|
+
t.integer :billable, default: 0
|
|
18
|
+
t.integer :work_break, default: 0
|
|
19
|
+
t.datetime :last_updated_at
|
|
20
|
+
|
|
21
|
+
t.timestamps
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
add_index :tudla_hubstaff_activities, :activity_id, unique: true
|
|
25
|
+
add_index :tudla_hubstaff_activities, :date
|
|
26
|
+
add_index :tudla_hubstaff_activities, :user_id
|
|
27
|
+
add_index :tudla_hubstaff_activities, :project_id
|
|
28
|
+
add_index :tudla_hubstaff_activities, :task_id
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class CreateTudlaHubstaffConfigs < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :tudla_hubstaff_configs do |t|
|
|
4
|
+
t.string :tudla_organization_type
|
|
5
|
+
t.bigint :tudla_organization_id
|
|
6
|
+
t.string :personal_access_token
|
|
7
|
+
t.bigint :organization_id
|
|
8
|
+
|
|
9
|
+
t.timestamps
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
add_index :tudla_hubstaff_configs, [ :tudla_organization_type, :tudla_organization_id ], name: "index_configs_on_tudla_organization"
|
|
13
|
+
add_index :tudla_hubstaff_configs, :organization_id
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class CreateTudlaHubstaffOrganizationUpdates < ActiveRecord::Migration[8.1]
|
|
2
|
+
def change
|
|
3
|
+
create_table :tudla_hubstaff_organization_updates do |t|
|
|
4
|
+
t.bigint :organization_id, null: false
|
|
5
|
+
t.datetime :last_updated_at
|
|
6
|
+
|
|
7
|
+
t.timestamps
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
add_index :tudla_hubstaff_organization_updates, :organization_id
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
require "rails/generators/base"
|
|
2
|
+
|
|
3
|
+
module TudlaHubstaff
|
|
4
|
+
module Generators
|
|
5
|
+
class ComponentsGenerator < Rails::Generators::Base
|
|
6
|
+
source_root File.expand_path("../../../app/components", __dir__)
|
|
7
|
+
|
|
8
|
+
desc "Copies TudlaHubstaff ViewComponents to the host application for customization."
|
|
9
|
+
|
|
10
|
+
argument :scope, required: false, default: nil,
|
|
11
|
+
desc: "The scope to copy (e.g., ui, or a specific component like ui/modal)"
|
|
12
|
+
|
|
13
|
+
class_option :force, type: :boolean, default: false,
|
|
14
|
+
desc: "Overwrite existing files"
|
|
15
|
+
|
|
16
|
+
class_option :templates_only, type: :boolean, default: false,
|
|
17
|
+
desc: "Copy only the template files (.html.erb), not the Ruby classes"
|
|
18
|
+
|
|
19
|
+
def copy_components
|
|
20
|
+
if scope.present?
|
|
21
|
+
copy_scoped_components
|
|
22
|
+
else
|
|
23
|
+
copy_all_components
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def copy_scoped_components
|
|
30
|
+
source_path = "tudla_hubstaff/#{scope}"
|
|
31
|
+
target_path = "app/components/tudla_hubstaff/#{scope}"
|
|
32
|
+
|
|
33
|
+
if options[:templates_only]
|
|
34
|
+
copy_templates_only(source_path, target_path)
|
|
35
|
+
else
|
|
36
|
+
if File.directory?(File.join(self.class.source_root, source_path))
|
|
37
|
+
directory source_path, target_path
|
|
38
|
+
say_status :success, "Copied #{scope} components to #{target_path}", :green
|
|
39
|
+
else
|
|
40
|
+
say_status :error, "No components found for scope '#{scope}'", :red
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def copy_all_components
|
|
46
|
+
if options[:templates_only]
|
|
47
|
+
copy_templates_only("tudla_hubstaff", "app/components/tudla_hubstaff")
|
|
48
|
+
else
|
|
49
|
+
directory "tudla_hubstaff", "app/components/tudla_hubstaff"
|
|
50
|
+
say_status :success, "Copied all TudlaHubstaff components to app/components/tudla_hubstaff", :green
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def copy_templates_only(source_path, target_path)
|
|
55
|
+
full_source = File.join(self.class.source_root, source_path)
|
|
56
|
+
|
|
57
|
+
Dir.glob(File.join(full_source, "**/*.html.erb")).each do |template_file|
|
|
58
|
+
relative_path = template_file.sub("#{self.class.source_root}/", "")
|
|
59
|
+
destination = relative_path.sub("tudla_hubstaff/", "app/components/tudla_hubstaff/")
|
|
60
|
+
|
|
61
|
+
copy_file relative_path, destination
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
say_status :success, "Copied component templates to #{target_path}", :green
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require "rails/generators/base"
|
|
2
|
+
|
|
3
|
+
module TudlaHubstaff
|
|
4
|
+
module Generators
|
|
5
|
+
class ViewsGenerator < Rails::Generators::Base
|
|
6
|
+
source_root File.expand_path("../../../app/views", __dir__)
|
|
7
|
+
|
|
8
|
+
desc "Copies TudlaHubstaff views to the host application for customization."
|
|
9
|
+
|
|
10
|
+
argument :scope, required: false, default: nil,
|
|
11
|
+
desc: "The scope to copy (e.g., users, tasks, projects, layouts)"
|
|
12
|
+
|
|
13
|
+
class_option :force, type: :boolean, default: false,
|
|
14
|
+
desc: "Overwrite existing files"
|
|
15
|
+
|
|
16
|
+
AVAILABLE_SCOPES = %w[users tasks projects layouts shared].freeze
|
|
17
|
+
|
|
18
|
+
def copy_views
|
|
19
|
+
if scope.present?
|
|
20
|
+
validate_scope!
|
|
21
|
+
copy_scoped_views
|
|
22
|
+
else
|
|
23
|
+
copy_all_views
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def validate_scope!
|
|
30
|
+
return if AVAILABLE_SCOPES.include?(scope)
|
|
31
|
+
|
|
32
|
+
say_status :error, "Invalid scope '#{scope}'. Available scopes: #{AVAILABLE_SCOPES.join(', ')}", :red
|
|
33
|
+
raise Thor::Error, "Invalid scope"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def copy_scoped_views
|
|
37
|
+
source_path = "tudla_hubstaff/#{scope}"
|
|
38
|
+
target_path = "app/views/tudla_hubstaff/#{scope}"
|
|
39
|
+
|
|
40
|
+
if File.directory?(File.join(self.class.source_root, source_path))
|
|
41
|
+
directory source_path, target_path
|
|
42
|
+
say_status :success, "Copied #{scope} views to #{target_path}", :green
|
|
43
|
+
else
|
|
44
|
+
say_status :error, "No views found for scope '#{scope}'", :red
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def copy_all_views
|
|
49
|
+
directory "tudla_hubstaff", "app/views/tudla_hubstaff"
|
|
50
|
+
say_status :success, "Copied all TudlaHubstaff views to app/views/tudla_hubstaff", :green
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# desc "Explaining what the task does"
|
|
2
|
+
# task :tudla_hubstaff do
|
|
3
|
+
# # Task goes here
|
|
4
|
+
# end
|
|
5
|
+
namespace :app do
|
|
6
|
+
namespace :tailwindcss do
|
|
7
|
+
desc "Watch and build Tailwind CSS for the engine"
|
|
8
|
+
task :watch do
|
|
9
|
+
require "tailwindcss-rails"
|
|
10
|
+
# Construct the command to watch engine files and output to builds/
|
|
11
|
+
cmd = "#{Tailwindcss::Commands.executable} " \
|
|
12
|
+
"-i #{TudlaHubstaff::Engine.root.join("app/assets/stylesheets/tudla_hubstaff/application.css")} " \
|
|
13
|
+
"-o #{TudlaHubstaff::Engine.root.join("app/assets/builds/tudla_hubstaff.css")} " \
|
|
14
|
+
"--watch"
|
|
15
|
+
system cmd
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
module TudlaHubstaff
|
|
2
|
+
class Engine < ::Rails::Engine
|
|
3
|
+
isolate_namespace TudlaHubstaff
|
|
4
|
+
|
|
5
|
+
# Configure Zeitwerk to use UI instead of Ui for the ui directory
|
|
6
|
+
initializer "tudla_hubstaff.zeitwerk_inflections", before: :set_autoload_paths do
|
|
7
|
+
Rails.autoloaders.each do |autoloader|
|
|
8
|
+
autoloader.inflector.inflect("ui" => "UI")
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
config.generators do |g|
|
|
13
|
+
g.test_framework :rspec
|
|
14
|
+
g.fixture_replacement :factory_bot
|
|
15
|
+
g.factory_bot dir: "spec/factories"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Advanced FactoryBot Configuration
|
|
19
|
+
# We hook into the initializer to append the path relative to the Engine's root.
|
|
20
|
+
initializer "tudla_hubstaff.factories", after: "factory_bot.set_factory_paths" do
|
|
21
|
+
if defined?(FactoryBot)
|
|
22
|
+
FactoryBot.definition_file_paths << File.expand_path("../../../spec/factories", __FILE__)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Define an initializer that runs when the app boots
|
|
27
|
+
initializer "tudla_hubstaff.register_integration",
|
|
28
|
+
after: "app.load_config_initializers" do
|
|
29
|
+
config.to_prepare do
|
|
30
|
+
# Register this gem's classes
|
|
31
|
+
Rails.logger.info "Registering Hubstaff integration"
|
|
32
|
+
TudlaContracts::Integrations::Registry.register(
|
|
33
|
+
"hubstaff",
|
|
34
|
+
type: "time_sheet",
|
|
35
|
+
provider_class: "TudlaHubstaff::Provider",
|
|
36
|
+
config_class: "TudlaHubstaff::Config"
|
|
37
|
+
)
|
|
38
|
+
TudlaContracts::Integrations::Registry.register_view_for_slot(
|
|
39
|
+
"task_show_tab",
|
|
40
|
+
TudlaContracts::Integrations::ViewDefinitions::ShowTabDefinition.new(
|
|
41
|
+
id: :tudla_hubstaff_task_show_tab,
|
|
42
|
+
label: "Hubstaff Activities",
|
|
43
|
+
component_class: TudlaHubstaff::TaskActivitiesComponent,
|
|
44
|
+
priority: 10,
|
|
45
|
+
if: ->(task) { true }
|
|
46
|
+
)
|
|
47
|
+
)
|
|
48
|
+
TudlaContracts::Integrations::Registry.register_view_for_slot(
|
|
49
|
+
"dashboard_section",
|
|
50
|
+
TudlaContracts::Integrations::ViewDefinitions::DashboardSectionDefinition.new(
|
|
51
|
+
id: :tudla_hubstaff_dashboard_section,
|
|
52
|
+
label: "Hubstaff Activities",
|
|
53
|
+
component_class: TudlaHubstaff::UserActivitiesListComponent,
|
|
54
|
+
priority: 10,
|
|
55
|
+
if: ->(user) { true }
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
initializer "tudla_hubstaff.importmap", before: "importmap" do |app|
|
|
62
|
+
if app.config.respond_to?(:importmap)
|
|
63
|
+
app.config.importmap.paths << Engine.root.join("config/importmap.rb")
|
|
64
|
+
app.config.importmap.cache_sweepers << Engine.root.join("app/javascript")
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
initializer "tudla_hubstaff.assets" do |app|
|
|
69
|
+
if app.config.respond_to?(:assets)
|
|
70
|
+
app.config.assets.paths << Engine.root.join("app/javascript")
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Ensure the engine's assets are visible to the host's pipeline
|
|
75
|
+
initializer "tudla_hubstaff.assets.precompile" do |app|
|
|
76
|
+
app.config.assets.paths << root.join("app/assets/tailwind")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
initializer "tudla_hubstaff.view_component" do |app|
|
|
80
|
+
# ViewComponent automatically picks up components from app/components
|
|
81
|
+
# No additional configuration needed when using autoload_paths
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Configurable layout - allows host app to specify which layout to use
|
|
85
|
+
config.tudla_hubstaff = ActiveSupport::OrderedOptions.new
|
|
86
|
+
config.tudla_hubstaff.layout = "tudla_hubstaff/application"
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Requires are necessary for the Engine to load these gems' tasks and classes
|
|
2
|
+
require "solid_queue"
|
|
3
|
+
require "solid_cache"
|
|
4
|
+
require "solid_cable"
|
|
5
|
+
require "tailwindcss-rails"
|
|
6
|
+
require "importmap-rails"
|
|
7
|
+
require "faraday"
|
|
8
|
+
require "httpx/adapters/faraday"
|
|
9
|
+
require "openid_connect"
|
|
10
|
+
require "tudla_contracts"
|
|
11
|
+
require "turbo-rails"
|
|
12
|
+
require "view_component"
|
|
13
|
+
require "pagy"
|
|
14
|
+
|
|
15
|
+
require "tudla_hubstaff/version"
|
|
16
|
+
require "tudla_hubstaff/provider"
|
|
17
|
+
require "tudla_hubstaff/engine"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
module TudlaHubstaff
|
|
21
|
+
class << self
|
|
22
|
+
# Configuration for the host interface class
|
|
23
|
+
# Host apps should set this to their own class that inherits from
|
|
24
|
+
# TudlaContracts::Integration::HostInterface
|
|
25
|
+
attr_writer :host_interface_class
|
|
26
|
+
|
|
27
|
+
def host_interface_class
|
|
28
|
+
@host_interface_class || raise(<<~ERROR)
|
|
29
|
+
TudlaHubstaff.host_interface_class is not configured.
|
|
30
|
+
|
|
31
|
+
Please configure it in an initializer:
|
|
32
|
+
|
|
33
|
+
# config/initializers/tudla_hubstaff.rb
|
|
34
|
+
TudlaHubstaff.host_interface_class = "::HostInterface"
|
|
35
|
+
|
|
36
|
+
Your class should inherit from TudlaContracts::Integration::HostInterface
|
|
37
|
+
and implement the required methods like `available_users_for_user`.
|
|
38
|
+
ERROR
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def host_interface
|
|
42
|
+
@host_interface ||= host_interface_class.constantize.new
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def reset_host_interface!
|
|
46
|
+
@host_interface = nil
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|