perilune 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/README.md +28 -0
- data/Rakefile +8 -0
- data/app/assets/config/perilune_manifest.js +1 -0
- data/app/assets/stylesheets/perilune/application.css +15 -0
- data/app/controllers/perilune/application_controller.rb +6 -0
- data/app/controllers/perilune/home_controller.rb +7 -0
- data/app/controllers/perilune/tasks_controller.rb +48 -0
- data/app/helpers/perilune/application_helper.rb +22 -0
- data/app/jobs/perilune/application_job.rb +6 -0
- data/app/jobs/perilune/tasks/executor_job.rb +37 -0
- data/app/mailers/perilune/application_mailer.rb +8 -0
- data/app/models/perilune/application_record.rb +7 -0
- data/app/models/perilune/task.rb +23 -0
- data/app/operations/perilune/tasks/create_operation.rb +51 -0
- data/app/operations/perilune/tasks/exports/create_operation.rb +44 -0
- data/app/operations/perilune/tasks/find_operation.rb +7 -0
- data/app/operations/perilune/tasks/search_operation.rb +8 -0
- data/app/serializers/perilune/tasks/serializer.rb +18 -0
- data/app/views/kaminari/_first_page.html.haml +5 -0
- data/app/views/kaminari/_gap.html.haml +1 -0
- data/app/views/kaminari/_last_page.html.haml +5 -0
- data/app/views/kaminari/_next_page.html.haml +5 -0
- data/app/views/kaminari/_page.html.haml +4 -0
- data/app/views/kaminari/_paginator.html.haml +11 -0
- data/app/views/kaminari/_prev_page.html.haml +5 -0
- data/app/views/layouts/perilune/application.html.haml +66 -0
- data/app/views/perilune/home/index.html.haml +19 -0
- data/app/views/perilune/tasks/index.html.haml +43 -0
- data/app/views/perilune/tasks/show.html.haml +44 -0
- data/config/routes.rb +6 -0
- data/lib/perilune/engine.rb +7 -0
- data/lib/perilune/tasks/mixin.rb +64 -0
- data/lib/perilune/version.rb +5 -0
- data/lib/perilune.rb +8 -0
- data/lib/tasks/perilune_tasks.rake +5 -0
- metadata +186 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fb116ba6c86f1c24f6981261f9c69335e2b152c1167708c411c41a408dd43893
|
4
|
+
data.tar.gz: ad39ec022a048edde5c3e18df3e3e62dd5eb75a117ce8a5103dab4c4516876ae
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 70f2a6f2fcf043f114818939c498fd85a14e183dd78bd3bdb91a2a32608ad94a5fea982c193b912e82530b9f66c95005ca662ca493370265e822d70146d65851
|
7
|
+
data.tar.gz: c271e506ffd1642a4de1f11e2e81c7abcdbe7566d285e3b67bcee169b52491e67a9c48514b4c1ae8170440c4404faa41bd4af7decd3db48c44727f48c2ebc9a9
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Perilune
|
2
|
+
Short description and motivation.
|
3
|
+
|
4
|
+
## Usage
|
5
|
+
How to use my plugin.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem "perilune"
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
```bash
|
16
|
+
$ bundle
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
```bash
|
21
|
+
$ gem install perilune
|
22
|
+
```
|
23
|
+
|
24
|
+
## Contributing
|
25
|
+
Contribution directions go here.
|
26
|
+
|
27
|
+
## License
|
28
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets/perilune .css
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Perilune
|
4
|
+
class TasksController < Perilune::ApplicationController
|
5
|
+
before_action :set_resources, only: %i[index]
|
6
|
+
before_action :set_resource, only: %i[show]
|
7
|
+
|
8
|
+
def index; end
|
9
|
+
|
10
|
+
def show; end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def set_resources
|
15
|
+
resource_search_operation.perform
|
16
|
+
raise resource_search_operation.result.error unless resource_search_operation.success?
|
17
|
+
|
18
|
+
@resources = resource_search_operation.result.value
|
19
|
+
end
|
20
|
+
|
21
|
+
def resource_search_operation
|
22
|
+
@resource_search_operation ||= Perilune::Tasks::SearchOperation.new(
|
23
|
+
query: {},
|
24
|
+
limit: {},
|
25
|
+
includes: [],
|
26
|
+
order: 'id DESC',
|
27
|
+
page: params[:page] || 1,
|
28
|
+
per: 25,
|
29
|
+
domain: :perilune
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
def set_resource
|
34
|
+
resource_find_operation.perform
|
35
|
+
raise resource_find_operation.result.error unless resource_find_operation.success?
|
36
|
+
|
37
|
+
@resource = resource_find_operation.result.value
|
38
|
+
end
|
39
|
+
|
40
|
+
def resource_find_operation
|
41
|
+
@resource_find_operation ||= Perilune::Tasks::FindOperation.new(
|
42
|
+
id: params[:id],
|
43
|
+
limit: {},
|
44
|
+
domain: :perilune
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Perilune
|
4
|
+
module ApplicationHelper
|
5
|
+
def task_state(task) # rubocop:disable Metrics/MethodLength
|
6
|
+
case task.state.to_sym
|
7
|
+
when :draft
|
8
|
+
content_tag(:div, task.state,
|
9
|
+
class: 'inline-flex items-center px-2.5 py-0.5 rounded-sm text-sm font-medium uppercase bg-gray-500 text-gray-50') # rubocop:disable Layout/LineLength
|
10
|
+
when :uploaded
|
11
|
+
content_tag(:div, task.state,
|
12
|
+
class: 'inline-flex items-center px-2.5 py-0.5 rounded-sm text-sm font-medium uppercase bg-yellow-500 text-yellow-50') # rubocop:disable Layout/LineLength
|
13
|
+
when :processed
|
14
|
+
content_tag(:div, task.state,
|
15
|
+
class: 'inline-flex items-center px-2.5 py-0.5 rounded-sm text-sm font-medium uppercase bg-blue-500 text-blue-50') # rubocop:disable Layout/LineLength
|
16
|
+
when :failed
|
17
|
+
content_tag(:div, task.state,
|
18
|
+
class: 'inline-flex items-center px-2.5 py-0.5 rounded-sm text-sm font-medium uppercase bg-red-500 text-red-50') # rubocop:disable Layout/LineLength
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Perilune
|
4
|
+
module Tasks
|
5
|
+
class ExecutorJob < ApplicationJob
|
6
|
+
queue_as :default
|
7
|
+
|
8
|
+
class UndefinedTaskKlass < StandardError; end
|
9
|
+
|
10
|
+
def perform(task_id)
|
11
|
+
@task_id = task_id
|
12
|
+
executor.execute
|
13
|
+
executor.success? ? success : failure
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def task
|
19
|
+
@task ||= Perilune::Task.find(@task_id)
|
20
|
+
end
|
21
|
+
|
22
|
+
def success
|
23
|
+
task.update(state: 'processed')
|
24
|
+
end
|
25
|
+
|
26
|
+
def failure
|
27
|
+
task.update(state: 'failed', error_data: { executor_error: executor.errors })
|
28
|
+
end
|
29
|
+
|
30
|
+
def executor
|
31
|
+
raise UndefinedTaskKlass unless Object.const_defined?(task.task_klass)
|
32
|
+
|
33
|
+
@executor ||= task.task_klass.constantize.new(file: task.file.download, task: task)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Perilune
|
4
|
+
class Task < ApplicationRecord
|
5
|
+
self.table_name = 'perilune_tasks'
|
6
|
+
validates :state, inclusion: {
|
7
|
+
in: %w[draft uploaded processed failed],
|
8
|
+
message: '%<value>s is not a valid state'
|
9
|
+
}
|
10
|
+
validates :task_klass, presence: true
|
11
|
+
has_one_attached :file
|
12
|
+
|
13
|
+
def file_name
|
14
|
+
file.filename.to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
def file_url
|
18
|
+
file.url
|
19
|
+
rescue StandardError
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Perilune
|
4
|
+
module Tasks
|
5
|
+
class CreateOperation
|
6
|
+
include LedgerSync::Domains::Operation::Mixin
|
7
|
+
|
8
|
+
class Contract < LedgerSync::Ledgers::Contract
|
9
|
+
params do
|
10
|
+
required(:file).maybe(type?: File)
|
11
|
+
required(:file).maybe(type?: Tempfile)
|
12
|
+
required(:task_klass).filled(:string)
|
13
|
+
optional(:tags).filled(:array)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def operate
|
20
|
+
attach!
|
21
|
+
if task.save
|
22
|
+
Perilune::Tasks::ExecutorJob.perform_later(task.id)
|
23
|
+
success(true)
|
24
|
+
else
|
25
|
+
failure(task.errors.full_messages)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def task
|
30
|
+
@task ||= Perilune::Task.new(
|
31
|
+
state: 'draft',
|
32
|
+
task_klass: params[:task_klass],
|
33
|
+
tags: params[:tags]
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
def attach!
|
38
|
+
task.file.attach(
|
39
|
+
io: params[:file],
|
40
|
+
key: "perilune/#{ActiveStorage::Blob.generate_unique_secure_token}",
|
41
|
+
filename: "#{params[:task_klass]}_#{Time.zone.now.to_i}"
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
# override to use common serializer for all domain
|
46
|
+
def serializer_for(*)
|
47
|
+
Perilune::Tasks::Serializer.new
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Perilune
|
4
|
+
module Tasks
|
5
|
+
module Exports
|
6
|
+
class CreateOperation
|
7
|
+
include LedgerSync::Domains::Operation::Mixin
|
8
|
+
|
9
|
+
class Contract < LedgerSync::Ledgers::Contract
|
10
|
+
params do
|
11
|
+
required(:task_klass).filled(:string)
|
12
|
+
required(:attrs).filled(:hash)
|
13
|
+
optional(:tags).filled(:array)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def operate
|
20
|
+
if task.save
|
21
|
+
Perilune::Tasks::ExecutorJob.perform_later(task.id)
|
22
|
+
success(true)
|
23
|
+
else
|
24
|
+
failure(task.errors.full_messages)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def task
|
29
|
+
@task ||= Perilune::Task.new(
|
30
|
+
state: 'draft',
|
31
|
+
task_klass: params[:task_klass],
|
32
|
+
attrs: params[:attrs],
|
33
|
+
tags: params[:tags]
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
# override to use common serializer for all domain
|
38
|
+
def serializer_for(*)
|
39
|
+
Perilune::Tasks::Serializer.new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Perilune
|
4
|
+
module Tasks
|
5
|
+
class Serializer < LedgerSync::Domains::Serializer
|
6
|
+
attribute :id
|
7
|
+
attribute :task_klass
|
8
|
+
attribute :attrs
|
9
|
+
attribute :state
|
10
|
+
attribute :tags
|
11
|
+
attribute :error_data
|
12
|
+
attribute :created_at
|
13
|
+
attribute :updated_at
|
14
|
+
attribute :file_name
|
15
|
+
attribute :file_url
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
- unless current_page.first?
|
2
|
+
= link_to url, remote: remote, class: 'relative inline-flex items-center px-2 py-2. rounded-l-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50' do
|
3
|
+
%span.sr-only= raw(t 'views.pagination.first')
|
4
|
+
%svg.h-4.w-4{:fill => "none", :stroke => "currentColor", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
|
5
|
+
%path{:d => "M11 19l-7-7 7-7m8 14l-7-7 7-7", "stroke-linecap" => "round", "stroke-linejoin" => "round", "stroke-width" => "2"}
|
@@ -0,0 +1 @@
|
|
1
|
+
= link_to raw(t 'views.pagination.truncate'), '#', class: 'relative inline-flex items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700'
|
@@ -0,0 +1,5 @@
|
|
1
|
+
- unless current_page.last?
|
2
|
+
= link_to url, remote: remote, class: 'relative inline-flex items-center px-2 py-2 rounded-r-md border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50' do
|
3
|
+
%span.sr-only= raw(t 'views.pagination.last')
|
4
|
+
%svg.h-4.w-4{:fill => "none", :stroke => "currentColor", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
|
5
|
+
%path{:d => "M13 5l7 7-7 7M5 5l7 7-7 7", "stroke-linecap" => "round", "stroke-linejoin" => "round", "stroke-width" => "2"}
|
@@ -0,0 +1,5 @@
|
|
1
|
+
- unless current_page.last?
|
2
|
+
= link_to url, rel: 'next', remote: remote, class: 'relative inline-flex items-center px-2 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50' do
|
3
|
+
%span.sr-only= raw(t 'views.pagination.next')
|
4
|
+
%svg.h-4.w-4{:fill => "none", :stroke => "currentColor", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
|
5
|
+
%path{:d => "M9 5l7 7-7 7", "stroke-linecap" => "round", "stroke-linejoin" => "round", "stroke-width" => "2"}
|
@@ -0,0 +1,4 @@
|
|
1
|
+
- if page.current?
|
2
|
+
= link_to page, url, remote: remote, rel: page.rel, class: 'hidden md:inline-flex relative items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50'
|
3
|
+
- else
|
4
|
+
= link_to page, url, remote: remote, rel: page.rel, class: 'hidden md:inline-flex relative items-center px-4 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
= paginator.render do
|
2
|
+
%nav.relative.z-0.inline-flex.shadow-sm.-space-x-px{"aria-label" => "Pagination"}
|
3
|
+
= first_page_tag unless current_page.first?
|
4
|
+
= prev_page_tag unless current_page.first?
|
5
|
+
- each_page do |page|
|
6
|
+
- if page.left_outer? || page.right_outer? || page.inside_window?
|
7
|
+
= page_tag page
|
8
|
+
- elsif !page.was_truncated?
|
9
|
+
= gap_tag
|
10
|
+
= next_page_tag unless current_page.last?
|
11
|
+
= last_page_tag unless current_page.last?
|
@@ -0,0 +1,5 @@
|
|
1
|
+
- unless current_page.first?
|
2
|
+
= link_to url, rel: 'prev', remote: remote, class: 'relative inline-flex items-center px-2 py-2 border border-gray-300 bg-white text-sm font-medium text-gray-500 hover:bg-gray-50' do
|
3
|
+
%span.sr-only= raw(t 'views.pagination.previous')
|
4
|
+
%svg.h-4.w-4{:fill => "none", :stroke => "currentColor", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
|
5
|
+
%path{:d => "M15 19l-7-7 7-7", "stroke-linecap" => "round", "stroke-linejoin" => "round", "stroke-width" => "2"}
|
@@ -0,0 +1,66 @@
|
|
1
|
+
!!!
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%meta{:charset => "utf-8"}/
|
5
|
+
%meta{:content => "width=device-width, initial-scale=1.0", :name => "viewport"}/
|
6
|
+
%meta{:content => "IE=edge", "http-equiv" => "X-UA-Compatible"}/
|
7
|
+
%title= content_for?(:page_title) ? sanitize(yield(:page_title), tags: []) : "Perilune"
|
8
|
+
= csrf_meta_tags
|
9
|
+
= csp_meta_tag
|
10
|
+
%link{:href => "https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&display=swap", :rel => "stylesheet"}/
|
11
|
+
/ Favicons
|
12
|
+
%link{:rel => 'apple-touch-icon', :sizes => '180x180', :href => "#{main_app.root_url}favicons/apple-touch-icon.png"}
|
13
|
+
%link{:rel => 'icon', :sizes => '16x16', :href => "#{main_app.root_url}perilune/favicons/favicon-16x16.png"}
|
14
|
+
%link{:rel => 'icon', :sizes => '32x32', :href => "#{main_app.root_url}perilune/favicons/favicon-32x32.png"}
|
15
|
+
%link{:rel => 'icon', :sizes => '48x48', :href => "#{main_app.root_url}perilune/favicons/favicon.ico"}
|
16
|
+
%link{:rel => 'mask-icon', :href => "#{main_app.root_url}perilune/favicons/safari-pinned-tab.svg"}
|
17
|
+
%link{:rel => 'manifest', :href => "#{main_app.root_url}perilune/favicons/site.webmanifest"}
|
18
|
+
%meta{:content => "#{main_app.root_url}perilune/favicons/ms-tile-150x150.png", :name => "msapplication-TileImage"}/
|
19
|
+
= action_cable_meta_tag
|
20
|
+
|
21
|
+
%script{:src => "https://cdn.tailwindcss.com"}
|
22
|
+
|
23
|
+
%body
|
24
|
+
- if user_signed_in?
|
25
|
+
%input{id: 'user_locale', type: 'hidden', value: current_user.full_time_zone}
|
26
|
+
.min-h-screen.bg-gray-100
|
27
|
+
%nav.bg-white.shadow-sm{'x-data' => "{ isMobileVisible: false }"}
|
28
|
+
/ Desktop menu
|
29
|
+
.max-w-7xl.mx-auto.px-4.sm:px-6.lg:px-8
|
30
|
+
.flex.justify-between.h-16
|
31
|
+
.flex
|
32
|
+
.flex-shrink-0.flex.items-center.px-6
|
33
|
+
= link_to perilune.root_path, class: 'h-8 w-auto font-mono' do
|
34
|
+
%span.bg-clip-text.text-transparent.bg-gradient-to-r.bg-blue-200.from-blue-300.to-purple-400.text-2xl.font-bold Perilune
|
35
|
+
.hidden.sm:-my-px.sm:ml-6.sm:flex.sm:space-x-8
|
36
|
+
= link_to perilune.root_path, class: "border-transparent text-gray-500 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium hover:text-gray-700 hover:text-gray-300" do
|
37
|
+
Dashboard
|
38
|
+
= link_to perilune.tasks_path, class: "border-transparent text-gray-500 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium hover:text-gray-700 hover:text-gray-300" do
|
39
|
+
Tasks
|
40
|
+
|
41
|
+
/ Mobile menu, show/hide based on menu state.
|
42
|
+
#mobile-menu.sm:hidden{':class' => "isMobileVisible ? 'visible' : 'hidden'"}
|
43
|
+
.pt-2.pb-3.space-y-1
|
44
|
+
= link_to perilune.root_path, class: "text-gray-600 border-transparent block pl-3 pr-4 py-2 border-l-4 text-base font-medium hover:bg-gray-50 hover:border-gray-300 hover:text-gray-800" do
|
45
|
+
Dashboard
|
46
|
+
= link_to perilune.tasks_path, class: "text-gray-600 border-transparent block pl-3 pr-4 py-2 border-l-4 text-base font-medium hover:bg-gray-50 hover:border-gray-300 hover:text-gray-800" do
|
47
|
+
Tasks
|
48
|
+
|
49
|
+
|
50
|
+
.py-10
|
51
|
+
%main
|
52
|
+
.max-w-7xl.mx-auto.sm:px-6.lg:px-8
|
53
|
+
.mt-2.mx-6
|
54
|
+
- flash.each do |type, message|
|
55
|
+
- case type
|
56
|
+
- when :error
|
57
|
+
%div.p-4.mb-4.rounded-md.text-sm.font-medium.bg-red-100.text-red-800=message
|
58
|
+
- when :alert
|
59
|
+
%div.p-4.mb-4.rounded-md.text-sm.font-medium.bg-yellow-100.text-yellow-800=message
|
60
|
+
- when :notice
|
61
|
+
%div.p-4.mb-4.rounded-md.text-sm.font-medium.bg-indigo-100.text-indigo-800=message
|
62
|
+
- else
|
63
|
+
%div.p-4.mb-4.rounded-md.text-sm.font-medium.bg-indigo-100.text-indigo-800=message
|
64
|
+
= yield
|
65
|
+
|
66
|
+
= yield :javascript
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
.bg-white.overflow-hidden.shadow.rounded-lg
|
4
|
+
.px-4.py-5.sm:p-6
|
5
|
+
%div.mb-4
|
6
|
+
%span.text-2xl.font-bold perilune
|
7
|
+
[
|
8
|
+
= succeed '-i-loon' do
|
9
|
+
%span.font-bold per
|
10
|
+
]
|
11
|
+
%hr
|
12
|
+
%div.mt-4
|
13
|
+
.italic noun
|
14
|
+
%div.mt-2.ml-8
|
15
|
+
%span.text-gray-400 1
|
16
|
+
%span.ml-2 the point in a lunar orbit that is nearest to the moon.
|
17
|
+
%div.mt-2.ml-8
|
18
|
+
%span.text-gray-400 2
|
19
|
+
%span.ml-2 that thing that processes your files and makes your life a bit easier.
|
@@ -0,0 +1,43 @@
|
|
1
|
+
.flex.flex-col
|
2
|
+
.-my-2.overflow-x-auto.sm:-mx-6.lg:-mx-8
|
3
|
+
.py-2.align-middle.inline-block.min-w-full.sm:px-6.lg:px-8
|
4
|
+
.shadow.overflow-hidden.border-b.border-gray-200.sm:rounded-lg
|
5
|
+
%table.min-w-full.divide-y.divide-gray-200
|
6
|
+
%thead.bg-gray-50
|
7
|
+
%tr
|
8
|
+
%th.px-6.py-3.text-left.text-xs.font-medium.text-gray-500.uppercase.tracking-wider{:scope => "col"} ID
|
9
|
+
%th.px-6.py-3.text-left.text-xs.font-medium.text-gray-500.uppercase.tracking-wider{:scope => "col"} Task
|
10
|
+
%th.px-6.py-3.text-left.text-xs.font-medium.text-gray-500.uppercase.tracking-wider{:scope => "col"} State
|
11
|
+
%th.px-6.py-3.text-left.text-xs.font-medium.text-gray-500.uppercase.tracking-wider{:scope => "col"} Tags
|
12
|
+
%th.px-6.py-3.text-left.text-xs.font-medium.text-gray-500.uppercase.tracking-wider{:scope => "col"} Created At
|
13
|
+
%th.relative.px-6.py-3{:scope => "col"}
|
14
|
+
%span.sr-only Edit
|
15
|
+
%tbody
|
16
|
+
- @resources.each do |resource|
|
17
|
+
%tr.bg-white
|
18
|
+
%td.px-6.py-4.whitespace-nowrap.text-sm.font-medium.text-gray-600
|
19
|
+
= link_to resource.id, perilune.task_path(resource), class: 'text-indigo-400 hover:text-indigo-900'
|
20
|
+
%td.px-6.py-4.whitespace-nowrap.text-sm.text-gray-500
|
21
|
+
.rounded-sm.font-mono.text-sm.px-2.w-auto.max-w-max.break-normal.text-purple-500.bg-blue-100= resource.task_klass
|
22
|
+
%td.px-6.py-4.whitespace-nowrap.text-sm.text-gray-500= task_state(resource)
|
23
|
+
%td.px-6.py-4.whitespace-nowrap.text-sm.text-gray-500
|
24
|
+
- resource.tags.each do |tag|
|
25
|
+
%span.inline-flex.items-center.px-3.py-0.5.rounded-full.text-sm.font-medium.bg-blue-100.text-blue-800= tag
|
26
|
+
%td.px-6.py-4.whitespace-nowrap.text-sm.text-gray-500= resource.created_at.to_s
|
27
|
+
%td.px-6.py-4.whitespace-nowrap.text-right.text-sm.font-medium
|
28
|
+
= link_to perilune.task_path(resource) do
|
29
|
+
%svg.h-6.w-6.text-indigo-400.hover:text-indigo-900{:fill => "none", :stroke => "currentColor", :viewbox => "0 0 24 24", :xmlns => "http://www.w3.org/2000/svg"}
|
30
|
+
%path{:d => "M13 9l3 3m0 0l-3 3m3-3H8m13 0a9 9 0 11-18 0 9 9 0 0118 0z", "stroke-linecap" => "round", "stroke-linejoin" => "round", "stroke-width" => "2"}
|
31
|
+
|
32
|
+
.mt-2
|
33
|
+
.flex-1.flex.items-center.justify-between
|
34
|
+
%div.hidden.sm:block
|
35
|
+
%p.text-sm.text-gray-400
|
36
|
+
- unless @resources.total_count.zero?
|
37
|
+
Showing
|
38
|
+
%span.font-medium= (@resources.current_page - 1) * @resources.limit_value + 1
|
39
|
+
to
|
40
|
+
%span.font-medium= [(@resources.current_page - 1) * @resources.limit_value + @resources.limit_value, @resources.total_count].min
|
41
|
+
of
|
42
|
+
= pluralize(@resources.total_count, 'task')
|
43
|
+
= paginate @resources
|
@@ -0,0 +1,44 @@
|
|
1
|
+
.bg-white.shadow.overflow-hidden.sm:rounded-lg
|
2
|
+
.px-4.py-5.sm:px-6
|
3
|
+
%h3.text-lg.leading-6.font-medium.text-gray-900 Task ##{@resource.id}
|
4
|
+
.border-t.border-gray-200.px-4.py-5.sm:p-0
|
5
|
+
%dl.sm:divide-y.sm:divide-gray-200
|
6
|
+
.py-4.sm:py-5.sm:grid.sm:grid-cols-3.sm:gap-4.sm:px-6
|
7
|
+
%dt.text-sm.font-medium.text-gray-500 Task Klass
|
8
|
+
%dd.mt-1.text-sm.text-gray-900.sm:mt-0.sm:col-span-2
|
9
|
+
.rounded-sm.font-mono.text-sm.px-2.w-auto.max-w-max.break-normal.text-purple-500.bg-blue-100 #{@resource.task_klass}
|
10
|
+
.py-4.sm:py-5.sm:grid.sm:grid-cols-3.sm:gap-4.sm:px-6
|
11
|
+
%dt.text-sm.font-medium.text-gray-500 Task Attributes
|
12
|
+
%dd.mt-1.text-sm.text-gray-900.sm:mt-0.sm:col-span-2
|
13
|
+
%code #{@resource.attrs}
|
14
|
+
.py-4.sm:py-5.sm:grid.sm:grid-cols-3.sm:gap-4.sm:px-6
|
15
|
+
%dt.text-sm.font-medium.text-gray-500 State
|
16
|
+
%dd.mt-1.text-sm.text-gray-900.sm:mt-0.sm:col-span-2 #{task_state(@resource)}
|
17
|
+
.py-4.sm:py-5.sm:grid.sm:grid-cols-3.sm:gap-4.sm:px-6
|
18
|
+
%dt.text-sm.font-medium.text-gray-500 Tags
|
19
|
+
%dd.mt-1.text-sm.text-gray-900.sm:mt-0.sm:col-span-2
|
20
|
+
- @resource.tags.each do |tag|
|
21
|
+
%span.inline-flex.items-center.px-3.py-0.5.rounded-full.text-sm.font-medium.bg-blue-100.text-blue-800= tag
|
22
|
+
.py-4.sm:py-5.sm:grid.sm:grid-cols-3.sm:gap-4.sm:px-6
|
23
|
+
%dt.text-sm.font-medium.text-gray-500 Created At
|
24
|
+
%dd.mt-1.text-sm.text-gray-900.sm:mt-0.sm:col-span-2 #{@resource.created_at.to_s}
|
25
|
+
.py-4.sm:py-5.sm:grid.sm:grid-cols-3.sm:gap-4.sm:px-6
|
26
|
+
%dt.text-sm.font-medium.text-gray-500 Updated At
|
27
|
+
%dd.mt-1.text-sm.text-gray-900.sm:mt-0.sm:col-span-2 #{@resource.updated_at.to_s}
|
28
|
+
- if @resource.state.to_sym == :failed
|
29
|
+
.py-4.sm:py-5.sm:grid.sm:grid-cols-3.sm:gap-4.sm:px-6
|
30
|
+
%dt.text-sm.font-medium.text-gray-500 Error
|
31
|
+
%dd.mt-1.text-sm.text-gray-900.sm:mt-0.sm:col-span-2
|
32
|
+
%code #{@resource.error_data}
|
33
|
+
.py-4.sm:py-5.sm:grid.sm:grid-cols-3.sm:gap-4.sm:px-6
|
34
|
+
%dt.text-sm.font-medium.text-gray-500 Attachment
|
35
|
+
%dd.mt-1.text-sm.text-gray-900.sm:mt-0.sm:col-span-2
|
36
|
+
%ul.border.border-gray-200.rounded-md.divide-y.divide-gray-200{:role => "list"}
|
37
|
+
%li.pl-3.pr-4.py-3.flex.items-center.justify-between.text-sm
|
38
|
+
.w-0.flex-1.flex.items-center
|
39
|
+
/ Heroicon name: solid/paper-clip
|
40
|
+
%svg.flex-shrink-0.h-5.w-5.text-gray-400{"aria-hidden" => "true", :fill => "currentColor", :viewbox => "0 0 20 20", :xmlns => "http://www.w3.org/2000/svg"}
|
41
|
+
%path{"clip-rule" => "evenodd", :d => "M8 4a3 3 0 00-3 3v4a5 5 0 0010 0V7a1 1 0 112 0v4a7 7 0 11-14 0V7a5 5 0 0110 0v4a3 3 0 11-6 0V7a1 1 0 012 0v4a1 1 0 102 0V7a3 3 0 00-3-3z", "fill-rule" => "evenodd"}
|
42
|
+
%span.ml-2.flex-1.w-0.truncate #{@resource.file_name}
|
43
|
+
.ml-4.flex-shrink-0
|
44
|
+
= link_to 'Download', @resource.file_url, class: 'font-medium text-indigo-400 hover:text-indigo-900'
|
data/config/routes.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Perilune
|
4
|
+
module Tasks
|
5
|
+
module Mixin
|
6
|
+
def self.included(base)
|
7
|
+
base.include InstanceMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
module InstanceMethods
|
11
|
+
attr_reader :file, :task, :errors
|
12
|
+
|
13
|
+
delegate :trace, to: :tracer
|
14
|
+
|
15
|
+
def initialize(file:, task:)
|
16
|
+
@file = file
|
17
|
+
@task = task
|
18
|
+
end
|
19
|
+
|
20
|
+
def execute
|
21
|
+
operate
|
22
|
+
rescue StandardError => e
|
23
|
+
failure(e.message)
|
24
|
+
end
|
25
|
+
|
26
|
+
def tags
|
27
|
+
task.tags
|
28
|
+
end
|
29
|
+
|
30
|
+
def failure(message)
|
31
|
+
@errors = message
|
32
|
+
end
|
33
|
+
|
34
|
+
def success?
|
35
|
+
errors.blank?
|
36
|
+
end
|
37
|
+
|
38
|
+
def operate(*)
|
39
|
+
raise StandardError, 'operate function is not defined'
|
40
|
+
end
|
41
|
+
|
42
|
+
def tracer_config
|
43
|
+
@tracer_config ||= Trifle::Logger::Configuration.new
|
44
|
+
@tracer_config.on(:wrapup) do |tracer|
|
45
|
+
entry = Perilune::Task.find_by(id: tracer.reference)
|
46
|
+
next if entry.nil?
|
47
|
+
|
48
|
+
entry.update(
|
49
|
+
tracer_data: tracer.data,
|
50
|
+
state: tracer.state
|
51
|
+
)
|
52
|
+
end
|
53
|
+
@tracer_config
|
54
|
+
end
|
55
|
+
|
56
|
+
def tracer
|
57
|
+
@tracer ||= Trifle::Logger.tracer = Trifle::Logger::Tracer::Hash.new(
|
58
|
+
key: task.id, reference: task.id, config: tracer_config
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/perilune.rb
ADDED
metadata
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: perilune
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kartavya Pareek
|
8
|
+
- Jozef Vaclavik
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2022-03-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: ledger_sync-domains
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 1.1.1
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 1.1.1
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rails
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 7.0.0
|
35
|
+
- - ">="
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 7.0.0.0
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - "~>"
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 7.0.0
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 7.0.0.0
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: trifle-logger
|
50
|
+
requirement: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: dotenv-rails
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
type: :development
|
70
|
+
prerelease: false
|
71
|
+
version_requirements: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: factory_bot_rails
|
78
|
+
requirement: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
name: pg
|
92
|
+
requirement: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
type: :development
|
98
|
+
prerelease: false
|
99
|
+
version_requirements: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
- !ruby/object:Gem::Dependency
|
105
|
+
name: rspec-rails
|
106
|
+
requirement: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
type: :development
|
112
|
+
prerelease: false
|
113
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
description: Description of Perilune.
|
119
|
+
email:
|
120
|
+
- hi@dropbot.sh
|
121
|
+
executables: []
|
122
|
+
extensions: []
|
123
|
+
extra_rdoc_files: []
|
124
|
+
files:
|
125
|
+
- README.md
|
126
|
+
- Rakefile
|
127
|
+
- app/assets/config/perilune_manifest.js
|
128
|
+
- app/assets/stylesheets/perilune/application.css
|
129
|
+
- app/controllers/perilune/application_controller.rb
|
130
|
+
- app/controllers/perilune/home_controller.rb
|
131
|
+
- app/controllers/perilune/tasks_controller.rb
|
132
|
+
- app/helpers/perilune/application_helper.rb
|
133
|
+
- app/jobs/perilune/application_job.rb
|
134
|
+
- app/jobs/perilune/tasks/executor_job.rb
|
135
|
+
- app/mailers/perilune/application_mailer.rb
|
136
|
+
- app/models/perilune/application_record.rb
|
137
|
+
- app/models/perilune/task.rb
|
138
|
+
- app/operations/perilune/tasks/create_operation.rb
|
139
|
+
- app/operations/perilune/tasks/exports/create_operation.rb
|
140
|
+
- app/operations/perilune/tasks/find_operation.rb
|
141
|
+
- app/operations/perilune/tasks/search_operation.rb
|
142
|
+
- app/serializers/perilune/tasks/serializer.rb
|
143
|
+
- app/views/kaminari/_first_page.html.haml
|
144
|
+
- app/views/kaminari/_gap.html.haml
|
145
|
+
- app/views/kaminari/_last_page.html.haml
|
146
|
+
- app/views/kaminari/_next_page.html.haml
|
147
|
+
- app/views/kaminari/_page.html.haml
|
148
|
+
- app/views/kaminari/_paginator.html.haml
|
149
|
+
- app/views/kaminari/_prev_page.html.haml
|
150
|
+
- app/views/layouts/perilune/application.html.haml
|
151
|
+
- app/views/perilune/home/index.html.haml
|
152
|
+
- app/views/perilune/tasks/index.html.haml
|
153
|
+
- app/views/perilune/tasks/show.html.haml
|
154
|
+
- config/routes.rb
|
155
|
+
- lib/perilune.rb
|
156
|
+
- lib/perilune/engine.rb
|
157
|
+
- lib/perilune/tasks/mixin.rb
|
158
|
+
- lib/perilune/version.rb
|
159
|
+
- lib/tasks/perilune_tasks.rake
|
160
|
+
homepage: https://engineering.dropbot.sh
|
161
|
+
licenses:
|
162
|
+
- MIT
|
163
|
+
metadata:
|
164
|
+
homepage_uri: https://engineering.dropbot.sh
|
165
|
+
source_code_uri: https://github.com/sandbite/perilune
|
166
|
+
changelog_uri: https://github.com/sandbite/perilune/blob/main/CHANGELOG.md
|
167
|
+
post_install_message:
|
168
|
+
rdoc_options: []
|
169
|
+
require_paths:
|
170
|
+
- lib
|
171
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - ">="
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '2.7'
|
176
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
requirements: []
|
182
|
+
rubygems_version: 3.2.9
|
183
|
+
signing_key:
|
184
|
+
specification_version: 4
|
185
|
+
summary: Summary of Perilune.
|
186
|
+
test_files: []
|