initial commit

This commit is contained in:
Alex Turchyn
2023-05-21 17:59:36 +03:00
commit 97c462ead2
159 changed files with 10987 additions and 0 deletions
@@ -0,0 +1,15 @@
# frozen_string_literal: true
module Api
class ApiBaseController < ActionController::API
include ActiveStorage::SetCurrent
before_action :authenticate_user!
private
def current_account
current_user&.account
end
end
end
@@ -0,0 +1,20 @@
# frozen_string_literal: true
module Api
class AttachmentsController < ApiBaseController
skip_before_action :authenticate_user!
def create
submission = Submission.find_by!(slug: params[:submission_slug])
blob = ActiveStorage::Blob.find_signed(params[:blob_signed_id])
attachment = ActiveStorage::Attachment.create!(
blob:,
name: params[:name],
record: submission
)
render json: attachment.as_json(only: %i[uuid], methods: %i[url filename content_type])
end
end
end
+22
View File
@@ -0,0 +1,22 @@
# frozen_string_literal: true
module Api
class FlowsController < ApiBaseController
def update
@flow = current_account.flows.find(params[:id])
@flow.update!(flow_params)
render :ok
end
private
def flow_params
params.require(:flow).permit(:name,
schema: [%i[attachment_uuid name]],
fields: [[:uuid, :name, :type, :required,
{ options: [], areas: [%i[x y w h attachment_uuid page]] }]])
end
end
end
@@ -0,0 +1,31 @@
# frozen_string_literal: true
module Api
class FlowsDocumentsController < ApiBaseController
def create
@flow = current_account.flows.find(params[:flow_id])
documents =
params[:blobs].map do |blob|
blob = ActiveStorage::Blob.find_signed(blob[:signed_id])
document = @flow.documents.create!(blob:)
Flows::ProcessDocument.call(document)
end
schema = documents.map do |doc|
{ attachment_uuid: doc.uuid, name: doc.filename.base }
end
render json: {
schema:,
documents: documents.as_json(
include: {
preview_images: { methods: %i[url metadata filename] }
}
)
}
end
end
end
+25
View File
@@ -0,0 +1,25 @@
# frozen_string_literal: true
class ApplicationController < ActionController::Base
include ActiveStorage::SetCurrent
before_action :maybe_redirect_to_setup, unless: :signed_in?
before_action :authenticate_user!, unless: :devise_controller?
helper_method :button_title,
:current_account
private
def current_account
current_user&.account
end
def maybe_redirect_to_setup
redirect_to setup_index_path unless User.exists?
end
def button_title(title = 'Submit', disabled_with = 'Submitting...')
render_to_string(partial: 'shared/button_title', locals: { title:, disabled_with: })
end
end
+7
View File
@@ -0,0 +1,7 @@
# frozen_string_literal: true
class DashboardController < ApplicationController
def index
@flows = current_account.flows.active
end
end
@@ -0,0 +1,28 @@
# frozen_string_literal: true
class EmailSettingsController < ApplicationController
before_action :load_encrypted_config
def index; end
def create
if @encrypted_config.update(storage_configs)
redirect_to settings_email_index_path, notice: 'Changes have been saved'
else
render :index, status: :unprocessable_entity
end
end
private
def load_encrypted_config
@encrypted_config =
EncryptedConfig.find_or_initialize_by(account: current_account, key: EncryptedConfig::EMAIL_SMTP_KEY)
end
def storage_configs
params.require(:encrypted_config).permit(value: {}).tap do |e|
e[:value].compact_blank!
end
end
end
+36
View File
@@ -0,0 +1,36 @@
# frozen_string_literal: true
class FlowsController < ApplicationController
def show
@flow = current_account.flows.preload(documents_attachments: { preview_images_attachments: :blob })
.find(params[:id])
end
def new
@flow = current_account.flows.new
end
def create
@flow = current_account.flows.new(flow_params)
@flow.author = current_user
if @flow.save
redirect_to flow_path(@flow)
else
render turbo_stream: turbo_stream.replace(:modal, template: 'flows/new'), status: :unprocessable_entity
end
end
def destroy
@flow = current_account.flows.find(params[:id])
@flow.update!(deleted_at: Time.current)
redirect_to settings_users_path, notice: 'Flow has been archived.'
end
private
def flow_params
params.require(:flow).permit(:name, :schema)
end
end
@@ -0,0 +1,4 @@
# frozen_string_literal: true
class InvitationsController < Devise::PasswordsController
end
@@ -0,0 +1,23 @@
# frozen_string_literal: true
class RegistrationsController < Devise::RegistrationsController
private
def build_resource(_hash = {})
account = Account.new(account_params)
self.resource = account.users.new(user_params)
end
def user_params
return {} if params[:user].blank?
params.require(:user).permit(:first_name, :last_name, :email, :password)
end
def account_params
return {} if params[:account].blank?
params.require(:account).permit(:name)
end
end
@@ -0,0 +1,21 @@
# frozen_string_literal: true
class SendSubmissionEmailController < ApplicationController
layout 'flow'
skip_before_action :authenticate_user!
def success; end
def create
@submission = if params[:flow_slug]
Submission.joins(:flow).find_by!(email: params[:email], flow: { slug: params[:flow_slug] })
else
Submission.find_by!(slug: params[:submission_slug])
end
SubmissionMailer.copy_to_submitter(@submission).deliver_later!
redirect_to success_send_submission_email_index_path
end
end
+49
View File
@@ -0,0 +1,49 @@
# frozen_string_literal: true
class SetupController < ApplicationController
skip_before_action :maybe_redirect_to_setup
skip_before_action :authenticate_user!
before_action :redirect_to_root_if_signed, if: :signed_in?
before_action :ensure_first_user_not_created!
def index
@account = Account.new(account_params)
@user = @account.users.new(user_params)
end
def create
@account = Account.new(account_params)
@user = @account.users.new(user_params)
if @user.save
sign_in(@user)
redirect_to root_path
else
render :index, status: :unprocessable_entity
end
end
private
def user_params
return {} unless params[:user]
params.require(:user).permit(:first_name, :last_name, :email, :password)
end
def account_params
return {} unless params[:account]
params.require(:account).permit(:name)
end
def redirect_to_root_if_signed
redirect_to root_path, notice: 'You are already signed in'
end
def ensure_first_user_not_created!
redirect_to new_user_session_path, notice: 'Please sign in.' if User.exists?
end
end
+51
View File
@@ -0,0 +1,51 @@
# frozen_string_literal: true
class StartFlowController < ApplicationController
layout 'flow'
skip_before_action :authenticate_user!
before_action :load_flow
def show
@submission = @flow.submissions.new
end
def update
@submission = @flow.submissions.find_or_initialize_by(
deleted_at: nil, **submission_params
)
if @submission.completed_at?
redirect_to start_flow_completed_path(@flow.slug, email: submission_params[:email])
else
@submission.assign_attributes(
opened_at: Time.current,
ip: request.remote_ip,
ua: request.user_agent
)
if @submission.save
redirect_to submit_flow_path(@submission.slug)
else
render :show
end
end
end
def completed
@submission = @flow.submissions.find_by(email: params[:email])
end
private
def submission_params
params.require(:submission).permit(:email)
end
def load_flow
slug = params[:slug] || params[:start_flow_slug]
@flow = Flow.find_by!(slug:)
end
end
@@ -0,0 +1,32 @@
# frozen_string_literal: true
class StorageSettingsController < ApplicationController
before_action :load_encrypted_config
def index; end
def create
if @encrypted_config.update(storage_configs)
LoadActiveStorageConfigs.reload
redirect_to settings_storage_index_path, notice: 'Changes have been saved'
else
render :index, status: :unprocessable_entity
end
end
private
def load_encrypted_config
@encrypted_config =
EncryptedConfig.find_or_initialize_by(account: current_account, key: EncryptedConfig::FILES_STORAGE_KEY)
end
def storage_configs
params.require(:encrypted_config).permit(value: {}).tap do |e|
e[:value].compact_blank!
e.dig(:value, :configs)&.compact_blank!
end
end
end
+50
View File
@@ -0,0 +1,50 @@
# frozen_string_literal: true
class SubmissionsController < ApplicationController
before_action :load_flow, only: %i[index new create]
def index
@submissions = @flow.submissions.active
end
def show
@submission =
Submission.joins(:flow).where(flow: { account_id: current_account.id })
.preload(flow: { documents_attachments: { preview_images_attachments: :blob } })
.find(params[:id])
end
def new; end
def create
emails = params[:emails].to_s.scan(User::EMAIL_REGEXP)
submissions =
emails.map do |email|
submission = @flow.submissions.create!(email:, sent_at: params[:send_email] == '1' ? Time.current : nil)
if params[:send_email] == '1'
SubmissionMailer.invitation_email(submission, message: params[:message]).deliver_later!
end
submission
end
redirect_to flow_submissions_path(@flow), notice: "#{submissions.size} recepients added"
end
def destroy
submission = Submission.joins(:flow).where(flow: { account_id: current_account.id })
.find(params[:id])
submission.update!(deleted_at: Time.current)
redirect_to flow_submissions_path(submission.flow), notice: 'Submission has been archieved'
end
private
def load_flow
@flow = current_account.flows.find(params[:flow_id])
end
end
@@ -0,0 +1,13 @@
# frozen_string_literal: true
class SubmissionsDownloadController < ApplicationController
skip_before_action :authenticate_user!
def index
submission = Submission.find_by(slug: params[:submission_slug])
Submissions::GenerateResultAttachments.call(submission)
redirect_to submission.archive.url, allow_other_host: true
end
end
+28
View File
@@ -0,0 +1,28 @@
# frozen_string_literal: true
class SubmitFlowController < ApplicationController
layout 'flow'
skip_before_action :authenticate_user!
def show
@submission = Submission.preload(flow: { documents_attachments: { preview_images_attachments: :blob } })
.find_by!(slug: params[:slug])
return redirect_to submit_flow_completed_path(@submission.slug) if @submission.completed_at?
end
def update
submission = Submission.find_by!(slug: params[:slug])
submission.values.merge!(params[:values].to_unsafe_h)
submission.completed_at = Time.current if params[:completed] == 'true'
submission.save
head :ok
end
def completed
@submission = Submission.find_by!(slug: params[:submit_flow_slug])
end
end
+56
View File
@@ -0,0 +1,56 @@
# frozen_string_literal: true
class UsersController < ApplicationController
before_action :load_user, only: %i[edit update destroy]
def index
@users = current_account.users.active.order(id: :desc)
end
def new
@user = current_account.users.new
end
def edit; end
def create
@user = current_account.users.find_by(email: user_params[:email])&.tap do |user|
user.assign_attributes(user_params)
user.deleted_at = nil
end
@user ||= current_account.users.new(user_params)
if @user.save
UserMailer.invitation_email(@user).deliver_later!
redirect_to settings_users_path, notice: 'User has been invited.'
else
render turbo_stream: turbo_stream.replace(:modal, template: 'users/new'), status: :unprocessable_entity
end
end
def update
if @user.update(user_params.compact_blank)
redirect_to settings_users_path, notice: 'User has been updated.'
else
render turbo_stream: turbo_stream.replace(:modal, template: 'users/edit'), status: :unprocessable_entity
end
end
def destroy
@user.update!(deleted_at: Time.current)
redirect_to settings_users_path, notice: 'User has been removed.'
end
private
def load_user
@user = current_account.users.find(params[:id])
end
def user_params
params.require(:user).permit(:email, :first_name, :last_name, :password)
end
end