adjust templates, add timezone and locale
This commit is contained in:
@@ -21,6 +21,7 @@ gem 'pg'
|
|||||||
gem 'premailer-rails'
|
gem 'premailer-rails'
|
||||||
gem 'puma'
|
gem 'puma'
|
||||||
gem 'rails'
|
gem 'rails'
|
||||||
|
gem 'rails-i18n'
|
||||||
gem 'ruby-vips'
|
gem 'ruby-vips'
|
||||||
gem 'shakapacker'
|
gem 'shakapacker'
|
||||||
gem 'sqlite3'
|
gem 'sqlite3'
|
||||||
|
|||||||
@@ -352,6 +352,9 @@ GEM
|
|||||||
rails-html-sanitizer (1.6.0)
|
rails-html-sanitizer (1.6.0)
|
||||||
loofah (~> 2.21)
|
loofah (~> 2.21)
|
||||||
nokogiri (~> 1.14)
|
nokogiri (~> 1.14)
|
||||||
|
rails-i18n (7.0.7)
|
||||||
|
i18n (>= 0.7, < 2)
|
||||||
|
railties (>= 6.0.0, < 8)
|
||||||
railties (7.0.5)
|
railties (7.0.5)
|
||||||
actionpack (= 7.0.5)
|
actionpack (= 7.0.5)
|
||||||
activesupport (= 7.0.5)
|
activesupport (= 7.0.5)
|
||||||
@@ -511,6 +514,7 @@ DEPENDENCIES
|
|||||||
pry-rails
|
pry-rails
|
||||||
puma
|
puma
|
||||||
rails
|
rails
|
||||||
|
rails-i18n
|
||||||
rspec-rails
|
rspec-rails
|
||||||
rubocop
|
rubocop
|
||||||
rubocop-performance
|
rubocop-performance
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AccountsController < ApplicationController
|
||||||
|
LOCALE_OPTIONS = {
|
||||||
|
'en-US' => 'English (United States)',
|
||||||
|
'en-GB' => 'English (United Kingdom)',
|
||||||
|
'es-ES' => 'Spanish (Spain)',
|
||||||
|
'pt-PT' => 'Portuguese (Portugal)',
|
||||||
|
'de-DE' => 'German (Germany)'
|
||||||
|
}.freeze
|
||||||
|
|
||||||
|
def show; end
|
||||||
|
|
||||||
|
def update
|
||||||
|
current_account.update!(account_params)
|
||||||
|
|
||||||
|
@encrypted_config = EncryptedConfig.find_or_initialize_by(account: current_account,
|
||||||
|
key: EncryptedConfig::APP_URL_KEY)
|
||||||
|
@encrypted_config.update!(app_url_params)
|
||||||
|
|
||||||
|
Docuseal.refresh_default_url_options!
|
||||||
|
|
||||||
|
redirect_to settings_account_path, notice: 'Account information has been updated'
|
||||||
|
rescue ActiveRecord::RecordInvalid
|
||||||
|
render :show, status: :unprocessable_entity
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def account_params
|
||||||
|
params.require(:account).permit(:name, :timezone, :locale)
|
||||||
|
end
|
||||||
|
|
||||||
|
def app_url_params
|
||||||
|
params.require(:encrypted_config).permit(:value)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,13 +1,11 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class ProfileController < ApplicationController
|
class ProfileController < ApplicationController
|
||||||
before_action :load_encrypted_config, only: %i[index update_app_url]
|
|
||||||
|
|
||||||
def index; end
|
def index; end
|
||||||
|
|
||||||
def update_contact
|
def update_contact
|
||||||
if current_user.update(contact_params)
|
if current_user.update(contact_params)
|
||||||
redirect_to settings_profile_index_path, notice: 'Contact information successfully updated'
|
redirect_to settings_profile_index_path, notice: 'Contact information has been updated'
|
||||||
else
|
else
|
||||||
render :index, status: :unprocessable_entity
|
render :index, status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
@@ -16,17 +14,7 @@ class ProfileController < ApplicationController
|
|||||||
def update_password
|
def update_password
|
||||||
if current_user.update(password_params)
|
if current_user.update(password_params)
|
||||||
bypass_sign_in(current_user)
|
bypass_sign_in(current_user)
|
||||||
redirect_to settings_profile_index_path, notice: 'Password successfully changed'
|
redirect_to settings_profile_index_path, notice: 'Password has been changed'
|
||||||
else
|
|
||||||
render :index, status: :unprocessable_entity
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_app_url
|
|
||||||
if @encrypted_config.update(app_url_params)
|
|
||||||
Docuseal.refresh_default_url_options!
|
|
||||||
|
|
||||||
redirect_to settings_profile_index_path, notice: 'App URL successfully changed'
|
|
||||||
else
|
else
|
||||||
render :index, status: :unprocessable_entity
|
render :index, status: :unprocessable_entity
|
||||||
end
|
end
|
||||||
@@ -34,20 +22,11 @@ class ProfileController < ApplicationController
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def load_encrypted_config
|
|
||||||
@encrypted_config =
|
|
||||||
EncryptedConfig.find_or_initialize_by(account: current_account, key: EncryptedConfig::APP_URL_KEY)
|
|
||||||
end
|
|
||||||
|
|
||||||
def contact_params
|
def contact_params
|
||||||
params.require(:user).permit(:first_name, :last_name, :email, account_attributes: %i[name])
|
params.require(:user).permit(:first_name, :last_name, :email)
|
||||||
end
|
end
|
||||||
|
|
||||||
def password_params
|
def password_params
|
||||||
params.require(:user).permit(:password, :password_confirmation)
|
params.require(:user).permit(:password, :password_confirmation)
|
||||||
end
|
end
|
||||||
|
|
||||||
def app_url_params
|
|
||||||
params.require(:encrypted_config).permit(:value)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ class RegistrationsController < Devise::RegistrationsController
|
|||||||
|
|
||||||
def build_resource(_hash = {})
|
def build_resource(_hash = {})
|
||||||
account = Account.new(account_params)
|
account = Account.new(account_params)
|
||||||
|
account.timezone = Accounts.normalize_timezone(account.timezone)
|
||||||
|
|
||||||
self.resource = account.users.new(user_params)
|
self.resource = account.users.new(user_params)
|
||||||
end
|
end
|
||||||
@@ -18,6 +19,6 @@ class RegistrationsController < Devise::RegistrationsController
|
|||||||
def account_params
|
def account_params
|
||||||
return {} if params[:account].blank?
|
return {} if params[:account].blank?
|
||||||
|
|
||||||
params.require(:account).permit(:name)
|
params.require(:account).permit(:name, :timezone)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ class SetupController < ApplicationController
|
|||||||
|
|
||||||
def create
|
def create
|
||||||
@account = Account.new(account_params)
|
@account = Account.new(account_params)
|
||||||
|
@account.timezone = Accounts.normalize_timezone(@account.timezone)
|
||||||
|
|
||||||
@user = @account.users.new(user_params)
|
@user = @account.users.new(user_params)
|
||||||
|
|
||||||
if @user.save
|
if @user.save
|
||||||
@@ -24,6 +26,8 @@ class SetupController < ApplicationController
|
|||||||
]
|
]
|
||||||
@account.encrypted_configs.create!(encrypted_configs)
|
@account.encrypted_configs.create!(encrypted_configs)
|
||||||
|
|
||||||
|
Docuseal.refresh_default_url_options!
|
||||||
|
|
||||||
sign_in(@user)
|
sign_in(@user)
|
||||||
|
|
||||||
redirect_to root_path
|
redirect_to root_path
|
||||||
@@ -43,7 +47,7 @@ class SetupController < ApplicationController
|
|||||||
def account_params
|
def account_params
|
||||||
return {} unless params[:account]
|
return {} unless params[:account]
|
||||||
|
|
||||||
params.require(:account).permit(:name)
|
params.require(:account).permit(:name, :timezone)
|
||||||
end
|
end
|
||||||
|
|
||||||
def encrypted_config_params
|
def encrypted_config_params
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class StartFormController < ApplicationController
|
|||||||
.find_or_initialize_by(**submitter_params)
|
.find_or_initialize_by(**submitter_params)
|
||||||
|
|
||||||
if @submitter.completed_at?
|
if @submitter.completed_at?
|
||||||
redirect_to start_form_completed_path(@template.slug, email: submission_params[:email])
|
redirect_to start_form_completed_path(@template.slug, email: submitter_params[:email])
|
||||||
else
|
else
|
||||||
@submitter.assign_attributes(
|
@submitter.assign_attributes(
|
||||||
uuid: @template.submitters.first['uuid'],
|
uuid: @template.submitters.first['uuid'],
|
||||||
@@ -36,7 +36,7 @@ class StartFormController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def completed
|
def completed
|
||||||
@submitter = Submitter.where(submission: @template.submitters).find_by(email: params[:email])
|
@submitter = Submitter.where(submission: @template.submissions).find_by!(email: params[:email])
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -46,7 +46,7 @@ class StartFormController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def load_template
|
def load_template
|
||||||
slug = params[:slug] || params[:start_template_slug]
|
slug = params[:slug] || params[:start_form_slug]
|
||||||
|
|
||||||
@template = Template.find_by!(slug:)
|
@template = Template.find_by!(slug:)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ class SubmitFormController < ApplicationController
|
|||||||
submitter = Submitter.find_by!(slug: params[:slug])
|
submitter = Submitter.find_by!(slug: params[:slug])
|
||||||
submitter.values.merge!(normalized_values)
|
submitter.values.merge!(normalized_values)
|
||||||
submitter.completed_at = Time.current if params[:completed] == 'true'
|
submitter.completed_at = Time.current if params[:completed] == 'true'
|
||||||
|
submitter.opened_at ||= Time.current
|
||||||
|
|
||||||
submitter.save!
|
submitter.save!
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import ClipboardCopy from './elements/clipboard_copy'
|
|||||||
import DynamicList from './elements/dynamic_list'
|
import DynamicList from './elements/dynamic_list'
|
||||||
import DownloadButton from './elements/download_button'
|
import DownloadButton from './elements/download_button'
|
||||||
import SetOriginUrl from './elements/set_origin_url'
|
import SetOriginUrl from './elements/set_origin_url'
|
||||||
|
import SetTimezone from './elements/set_timezone'
|
||||||
|
|
||||||
document.addEventListener('turbo:before-cache', () => {
|
document.addEventListener('turbo:before-cache', () => {
|
||||||
window.flash?.remove()
|
window.flash?.remove()
|
||||||
@@ -32,6 +33,7 @@ window.customElements.define('clipboard-copy', ClipboardCopy)
|
|||||||
window.customElements.define('dynamic-list', DynamicList)
|
window.customElements.define('dynamic-list', DynamicList)
|
||||||
window.customElements.define('download-button', DownloadButton)
|
window.customElements.define('download-button', DownloadButton)
|
||||||
window.customElements.define('set-origin-url', SetOriginUrl)
|
window.customElements.define('set-origin-url', SetOriginUrl)
|
||||||
|
window.customElements.define('set-timezone', SetTimezone)
|
||||||
|
|
||||||
window.customElements.define('template-builder', class extends HTMLElement {
|
window.customElements.define('template-builder', class extends HTMLElement {
|
||||||
connectedCallback () {
|
connectedCallback () {
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export default class extends HTMLElement {
|
||||||
|
connectedCallback () {
|
||||||
|
if (this.dataset.inputId) {
|
||||||
|
document.getElementById(this.dataset.inputId).value = Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -207,7 +207,7 @@ export default {
|
|||||||
},
|
},
|
||||||
formattedDate () {
|
formattedDate () {
|
||||||
if (this.field.type === 'date' && this.modelValue) {
|
if (this.field.type === 'date' && this.modelValue) {
|
||||||
return new Intl.DateTimeFormat({ year: 'numeric', month: 'numeric', day: 'numeric' }).format(new Date(this.modelValue))
|
return new Intl.DateTimeFormat([], { year: 'numeric', month: 'long', day: 'numeric' }).format(new Date(this.modelValue))
|
||||||
} else {
|
} else {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,10 @@
|
|||||||
>{{ currentField.name }}
|
>{{ currentField.name }}
|
||||||
<template v-if="!currentField.required">(optional)</template>
|
<template v-if="!currentField.required">(optional)</template>
|
||||||
</label>
|
</label>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="py-1"
|
||||||
|
/>
|
||||||
<div>
|
<div>
|
||||||
<input
|
<input
|
||||||
:id="currentField.uuid"
|
:id="currentField.uuid"
|
||||||
@@ -62,6 +66,10 @@
|
|||||||
>{{ currentField.name }}
|
>{{ currentField.name }}
|
||||||
<template v-if="!currentField.required">(optional)</template>
|
<template v-if="!currentField.required">(optional)</template>
|
||||||
</label>
|
</label>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="py-1"
|
||||||
|
/>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<input
|
<input
|
||||||
:id="currentField.uuid"
|
:id="currentField.uuid"
|
||||||
@@ -82,6 +90,10 @@
|
|||||||
>{{ currentField.name }}
|
>{{ currentField.name }}
|
||||||
<template v-if="!currentField.required">(optional)</template>
|
<template v-if="!currentField.required">(optional)</template>
|
||||||
</label>
|
</label>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="py-1"
|
||||||
|
/>
|
||||||
<select
|
<select
|
||||||
:id="currentField.uuid"
|
:id="currentField.uuid"
|
||||||
:required="currentField.required"
|
:required="currentField.required"
|
||||||
@@ -246,7 +258,7 @@
|
|||||||
:key="step[0].uuid"
|
:key="step[0].uuid"
|
||||||
href="#"
|
href="#"
|
||||||
class="inline border border-base-300 h-3 w-3 rounded-full mx-1"
|
class="inline border border-base-300 h-3 w-3 rounded-full mx-1"
|
||||||
:class="{ 'bg-base-200': index === currentStep, 'bg-base-content': index < currentStep || isCompleted, 'bg-white': index > currentStep }"
|
:class="{ 'bg-base-300': index === currentStep, 'bg-base-content': index < currentStep || isCompleted, 'bg-white': index > currentStep }"
|
||||||
@click.prevent="isCompleted ? '' : goToStep(step, true)"
|
@click.prevent="isCompleted ? '' : goToStep(step, true)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,7 +5,9 @@
|
|||||||
# Table name: accounts
|
# Table name: accounts
|
||||||
#
|
#
|
||||||
# id :bigint not null, primary key
|
# id :bigint not null, primary key
|
||||||
|
# locale :string not null
|
||||||
# name :string not null
|
# name :string not null
|
||||||
|
# timezone :string not null
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
#
|
#
|
||||||
@@ -15,4 +17,7 @@ class Account < ApplicationRecord
|
|||||||
has_many :templates, dependent: :destroy
|
has_many :templates, dependent: :destroy
|
||||||
has_many :active_users, -> { active }, dependent: :destroy,
|
has_many :active_users, -> { active }, dependent: :destroy,
|
||||||
inverse_of: :account, class_name: 'User'
|
inverse_of: :account, class_name: 'User'
|
||||||
|
|
||||||
|
attribute :timezone, :string, default: 'UTC'
|
||||||
|
attribute :locale, :string, default: 'en-US'
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -50,4 +50,8 @@ class Submitter < ApplicationRecord
|
|||||||
'awaiting'
|
'awaiting'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def status_event_at
|
||||||
|
completed_at || opened_at || sent_at || created_at
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -52,8 +52,6 @@ class User < ApplicationRecord
|
|||||||
|
|
||||||
scope :active, -> { where(deleted_at: nil) }
|
scope :active, -> { where(deleted_at: nil) }
|
||||||
|
|
||||||
accepts_nested_attributes_for :account, update_only: true
|
|
||||||
|
|
||||||
def active_for_authentication?
|
def active_for_authentication?
|
||||||
!deleted_at?
|
!deleted_at?
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<div class="flex flex-wrap space-y-4 md:flex-nowrap md:space-y-0">
|
||||||
|
<%= render 'shared/settings_nav' %>
|
||||||
|
<div class="flex-grow max-w-xl mx-auto">
|
||||||
|
<h1 class="text-4xl font-bold mb-4">Account</h1>
|
||||||
|
<%= form_for '', url: settings_account_path, method: :patch, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
||||||
|
<%= f.fields_for current_account do |ff| %>
|
||||||
|
<div class="form-control">
|
||||||
|
<%= ff.label :name, 'Company Name', class: 'label' %>
|
||||||
|
<%= ff.text_field :name, required: true, class: 'base-input' %>
|
||||||
|
</div>
|
||||||
|
<div class="grid md:grid-cols-2 gap-4">
|
||||||
|
<div class="form-control">
|
||||||
|
<%= ff.label :timezone, class: 'label' %>
|
||||||
|
<%= ff.select :timezone, nil, {}, class: 'select base-input w-full font-normal' do %>
|
||||||
|
<%= time_zone_options_for_select(current_account.timezone) %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<div class="form-control">
|
||||||
|
<%= ff.label :locale, 'Time format', class: 'label' %>
|
||||||
|
<%= ff.select :locale, options_for_select(controller.class::LOCALE_OPTIONS.invert, current_account.locale), {}, class: 'select base-input w-full font-normal' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<%= f.fields_for @encrypted_config || EncryptedConfig.find_or_initialize_by(account: current_account, key: EncryptedConfig::APP_URL_KEY) do |ff| %>
|
||||||
|
<div class="form-control">
|
||||||
|
<%= ff.label :value, 'App URL', class: 'label' %>
|
||||||
|
<%= ff.text_field :value, autocomplete: 'off', class: 'base-input' %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<div class="form-control pt-2">
|
||||||
|
<%= f.button button_title(title: 'Update', disabled_with: 'Updating'), class: 'base-button' %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<div class="w-0 md:w-52"></div>
|
||||||
|
</div>
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<p class="flex items-center space-x-1 text-xs text-base-content/60">
|
<p class="flex items-center space-x-1 text-xs text-base-content/60">
|
||||||
<%= svg_icon('calendar', class: 'w-4 h-4') %>
|
<%= svg_icon('calendar', class: 'w-4 h-4') %>
|
||||||
<span><%= l(template.created_at, format: :long) %></span>
|
<span><%= l(template.created_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %></span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
@@ -39,18 +39,22 @@
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<%= render 'shared/pagination', pagy: @pagy, items_name: 'Templates' %>
|
<%= render 'shared/pagination', pagy: @pagy, items_name: 'templates' %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<div class="card bg-base-200 h-96 mb-2">
|
<div class="card bg-base-200 h-96 mb-2">
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
<div class="flex items-center h-full">
|
<div class="flex items-center h-full">
|
||||||
<div class="max-w-lg mx-auto">
|
<div class="mx-auto">
|
||||||
<h1 class="text-5xl font-bold">Welcome to DocuSeal</h1>
|
<div class="max-w-xl mx-auto">
|
||||||
<p class="py-6">Streamline document workflows, from creating customizable templates to filling and signing document forms, with DocuSeal</p>
|
<h1 class="text-5xl font-bold text-base-content">👋 Welcome to DocuSeal</h1>
|
||||||
<%= link_to new_template_path, class: 'btn btn-neutral', data: { turbo_frame: :modal } do %>
|
</div>
|
||||||
<%= svg_icon('plus', class: 'w-6 h-6') %>
|
<div class="max-w-lg mx-auto">
|
||||||
<span>Create Template</span>
|
<p class="py-6 text-gray-600">Streamline document workflows, from creating customizable templates to filling and signing document forms, with DocuSeal</p>
|
||||||
<% end %>
|
<%= link_to new_template_path, class: 'base-button', data: { turbo_frame: :modal } do %>
|
||||||
|
<%= svg_icon('plus', class: 'w-6 h-6 stroke-2') %>
|
||||||
|
<span>Create Template</span>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,13 +4,21 @@
|
|||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<%= render 'devise/shared/error_messages', resource: %>
|
<%= render 'devise/shared/error_messages', resource: %>
|
||||||
<%= f.fields_for resource do |ff| %>
|
<%= f.fields_for resource do |ff| %>
|
||||||
<div class="form-control">
|
<div class="grid gap-2 md:grid-cols-2 md:gap-4">
|
||||||
<%= ff.label :first_name, class: 'label' %>
|
<div class="form-control">
|
||||||
<%= ff.text_field :first_name, required: true, class: 'base-input' %>
|
<%= ff.label :first_name, class: 'label' %>
|
||||||
|
<%= ff.text_field :first_name, required: true, class: 'base-input' %>
|
||||||
|
</div>
|
||||||
|
<div class="form-control">
|
||||||
|
<%= ff.label :last_name, class: 'label' %>
|
||||||
|
<%= ff.text_field :last_name, required: true, class: 'base-input' %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<%= f.fields_for resource do |ff| %>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= ff.label :last_name, class: 'label' %>
|
<%= ff.label :email, class: 'label' %>
|
||||||
<%= ff.text_field :last_name, required: true, class: 'base-input' %>
|
<%= ff.email_field :email, required: true, class: 'base-input' %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= f.fields_for resource.account do |ff| %>
|
<%= f.fields_for resource.account do |ff| %>
|
||||||
@@ -20,10 +28,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= f.fields_for resource do |ff| %>
|
<%= f.fields_for resource do |ff| %>
|
||||||
<div class="form-control">
|
|
||||||
<%= ff.label :email, class: 'label' %>
|
|
||||||
<%= ff.email_field :email, required: true, class: 'base-input' %>
|
|
||||||
</div>
|
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= ff.label :password, class: 'label' %>
|
<%= ff.label :password, class: 'label' %>
|
||||||
<%= ff.password_field :password, required: true, class: 'base-input' %>
|
<%= ff.password_field :password, required: true, class: 'base-input' %>
|
||||||
|
|||||||
@@ -2,9 +2,6 @@
|
|||||||
<%= render 'shared/settings_nav' %>
|
<%= render 'shared/settings_nav' %>
|
||||||
<div class="flex-grow max-w-xl mx-auto">
|
<div class="flex-grow max-w-xl mx-auto">
|
||||||
<h1 class="text-4xl font-bold mb-4">Email SMTP</h1>
|
<h1 class="text-4xl font-bold mb-4">Email SMTP</h1>
|
||||||
<p>
|
|
||||||
Configure your to send emails (TODO)
|
|
||||||
</p>
|
|
||||||
<% value = @encrypted_config.value || {} %>
|
<% value = @encrypted_config.value || {} %>
|
||||||
<%= form_for @encrypted_config, url: settings_email_index_path, method: :post, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
<%= form_for @encrypted_config, url: settings_email_index_path, method: :post, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
||||||
<%= f.fields_for :value do |ff| %>
|
<%= f.fields_for :value do |ff| %>
|
||||||
@@ -29,11 +26,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= ff.label :from_email, 'Send from', class: 'label' %>
|
<%= ff.label :from_email, 'Send from Email', class: 'label' %>
|
||||||
<%= ff.email_field :from_email, value: value['from_email'], required: true, class: 'base-input' %>
|
<%= ff.email_field :from_email, value: value['from_email'], required: true, class: 'base-input' %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<div class="form-control">
|
<div class="form-control pt-2">
|
||||||
<%= f.button button_title(title: 'Save', disabled_with: 'Saving'), class: 'base-button' %>
|
<%= f.button button_title(title: 'Save', disabled_with: 'Saving'), class: 'base-button' %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex items-center space-x-1">
|
<div class="flex items-center space-x-1">
|
||||||
<%= svg_icon('calendar', class: 'w-5 h-5 inline') %>
|
<%= svg_icon('calendar', class: 'w-5 h-5 inline') %>
|
||||||
<span><%= l(signature.signing_time, format: :long) %></span>
|
<span><%= l(signature.signing_time.in_time_zone(current_account.timezone), format: :long, locale: current_account.locale) %></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center space-x-1">
|
<div class="flex items-center space-x-1">
|
||||||
<%= svg_icon('certificate', class: 'w-5 h-5 inline') %>
|
<%= svg_icon('certificate', class: 'w-5 h-5 inline') %>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<div class="flex flex-wrap space-y-4 md:flex-nowrap md:space-y-0">
|
<div class="flex flex-wrap space-y-4 md:flex-nowrap md:space-y-0">
|
||||||
<%= render 'shared/settings_nav' %>
|
<%= render 'shared/settings_nav' %>
|
||||||
<div class="flex-grow max-w-xl mx-auto">
|
<div class="flex-grow max-w-xl mx-auto">
|
||||||
<h1 class="text-4xl font-bold mb-4">Verify PDF Signature</h1>
|
<h1 class="text-4xl font-bold mb-4">PDF Signature</h1>
|
||||||
<div id="result">
|
<div id="result">
|
||||||
<p class="mb-2">
|
<p class="mb-2">
|
||||||
Upload signed PDF file to validate its signature:
|
Upload signed PDF file to validate its signature:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<div class="max-w-xl mx-auto px-2">
|
<div class="max-w-xl mx-auto px-2">
|
||||||
<h1 class="text-4xl font-bold text-center my-8">Welcome to Docuseal</h1>
|
<h1 class="text-4xl font-bold text-center my-8">👋 Welcome to Docuseal</h1>
|
||||||
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put, class: 'space-y-6' }) do |f| %>
|
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put, class: 'space-y-6' }) do |f| %>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<%= render 'devise/shared/error_messages', resource: %>
|
<%= render 'devise/shared/error_messages', resource: %>
|
||||||
|
|||||||
@@ -8,65 +8,61 @@
|
|||||||
DocuSeal
|
DocuSeal
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<p class="mb-16 text-lg text-center text-gray-500">
|
<h2 class="mb-16 text-lg text-center text-gray-500">
|
||||||
A self-hosted, web-based platform providing secure and efficient digital document signing and transaction management.
|
A self-hosted and open-source web platform that provides secure and efficient digital document signing and processing.
|
||||||
</p>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-1 gap-12 md:gap-10 md:grid-cols-2">
|
<div class="grid grid-cols-1 gap-12 md:gap-10 md:grid-cols-2">
|
||||||
<div class="card bg-base-300">
|
<div class="card bg-base-200">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="text-center transition-all">
|
<div class="text-center transition-all">
|
||||||
<div class="inline-block p-4 mb-6 -mt-16 bg-base-content rounded-full">
|
<div class="inline-block p-4 mb-4 -mt-16 bg-base-content rounded-full">
|
||||||
<%= svg_icon('brand_docker', class: 'w-10 h-10 text-base-100 stroke-1') %>
|
<%= svg_icon('brand_docker', class: 'w-10 h-10 text-base-100 stroke-1') %>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="mb-4 text-2xl font-semibold">Easy to Install</h3>
|
<h3 class="mb-4 text-2xl font-semibold">Easy to Start</h3>
|
||||||
<p class="text-base text-gray-500">
|
<p class="text-base text-gray-500">
|
||||||
Simply initiate the process on your platform, deploy the solution via <a href="https://hub.docker.com/r/docuseal/docuseal" class="link link-neutral font-bold" target="_blank">Docker</a>,
|
Run on your own host using <a href="https://hub.docker.com/r/docuseal/docuseal" class="link link-neutral font-bold" target="_blank">Docker</a> container, or deploy on your favorite managed PaaS with a single <a href="https:///www.docuseal.co/install" class="link link-neutral font-bold">click</a>.
|
||||||
or opt for its packaged version for ease of use.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card bg-base-300">
|
<div class="card bg-base-200">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="text-center transition-all">
|
<div class="text-center transition-all">
|
||||||
<div class="inline-block p-4 mb-6 -mt-16 bg-base-content rounded-full">
|
<div class="inline-block p-4 mb-4 -mt-16 bg-base-content rounded-full">
|
||||||
<%= svg_icon('devices', class: 'w-10 h-10 text-base-100') %>
|
<%= svg_icon('devices', class: 'w-10 h-10 text-base-100') %>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="mb-4 text-2xl font-semibold">Mobile Optimized</h3>
|
<h3 class="mb-4 text-2xl font-semibold">Mobile Optimized</h3>
|
||||||
<p class="text-base text-gray-500">
|
<p class="text-base text-gray-500">
|
||||||
This self-hosted solution is mobile-ready, designed to offer a seamless user experience on any device.
|
Review and sign digital documents online from any device.
|
||||||
Manage documents with ease, right from your smartphone or tablet.
|
Docuseal document forms are optimized for screens of all sizes.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card bg-base-300">
|
<div class="card bg-base-200">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="text-center transition-all">
|
<div class="text-center transition-all">
|
||||||
<div class="inline-block p-4 mb-6 -mt-16 bg-base-content rounded-full">
|
<div class="inline-block p-4 mb-4 -mt-16 bg-base-content rounded-full">
|
||||||
<%= svg_icon('shield_check', class: 'w-10 h-10 text-base-100') %>
|
<%= svg_icon('shield_check', class: 'w-10 h-10 text-base-100') %>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="mb-4 text-2xl font-semibold">Secure</h3>
|
<h3 class="mb-4 text-2xl font-semibold">Secure</h3>
|
||||||
<p class="text-base text-gray-500">
|
<p class="text-base text-gray-500">
|
||||||
With a focus on security, this solution integrates top-level encryption within your own hosting infrastructure.
|
Host it on your hardware under a VPN to ensure that important documents can be accesses only within your organization.
|
||||||
Comprehensive tracking of every action assures a secure environment for all digital transactions.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card bg-base-300">
|
<div class="card bg-base-200">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="text-center transition-all">
|
<div class="text-center transition-all">
|
||||||
<div class="inline-block p-4 mb-6 -mt-16 bg-base-content rounded-full">
|
<div class="inline-block p-4 mb-4 -mt-16 bg-base-content rounded-full">
|
||||||
<%= svg_icon('brand_github', class: 'w-10 h-10 text-base-100') %>
|
<%= svg_icon('brand_github', class: 'w-10 h-10 text-base-100') %>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="mb-4 text-2xl font-semibold">Open Source</h3>
|
<h3 class="mb-4 text-2xl font-semibold">Open Source</h3>
|
||||||
<p class="text-base text-gray-500">
|
<p class="text-base text-gray-500">
|
||||||
Don't hesitate to fetch <a href="https://github.com/docusealhq" class="link link-neutral font-bold" target="_blank">github.com/docusealhq</a>.
|
Source code is available under <a href="https://github.com/docusealhq/docuseal" class="link link-neutral font-bold" target="_blank">github.com/docusealhq</a>.<br>Open-source contributors are always ready to help!
|
||||||
We warmly invite you to participate and help us enhance this project.
|
|
||||||
There's no need to shy away from becoming a contributor!
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,9 +2,6 @@
|
|||||||
<%= render 'shared/settings_nav' %>
|
<%= render 'shared/settings_nav' %>
|
||||||
<div class="flex-grow max-w-xl mx-auto">
|
<div class="flex-grow max-w-xl mx-auto">
|
||||||
<h1 class="text-4xl font-bold mb-4">Profile</h1>
|
<h1 class="text-4xl font-bold mb-4">Profile</h1>
|
||||||
<p>
|
|
||||||
Manage your contact information
|
|
||||||
</p>
|
|
||||||
<%= form_for current_user, url: update_contact_settings_profile_index_path, method: :patch, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
<%= form_for current_user, url: update_contact_settings_profile_index_path, method: :patch, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
||||||
<div class="grid md:grid-cols-2 gap-4">
|
<div class="grid md:grid-cols-2 gap-4">
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
@@ -20,13 +17,7 @@
|
|||||||
<%= f.label :email, 'Email', class: 'label' %>
|
<%= f.label :email, 'Email', class: 'label' %>
|
||||||
<%= f.email_field :email, autocomplete: 'off', class: 'base-input' %>
|
<%= f.email_field :email, autocomplete: 'off', class: 'base-input' %>
|
||||||
</div>
|
</div>
|
||||||
<%= f.fields_for :account do |ff| %>
|
<div class="form-control pt-2">
|
||||||
<div class="form-control">
|
|
||||||
<%= ff.label :name, 'Company Name', class: 'label' %>
|
|
||||||
<%= ff.text_field :name, required: true, class: 'base-input' %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
<div class="form-control">
|
|
||||||
<%= f.button button_title(title: 'Update', disabled_with: 'Updating'), class: 'base-button' %>
|
<%= f.button button_title(title: 'Update', disabled_with: 'Updating'), class: 'base-button' %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -40,16 +31,7 @@
|
|||||||
<%= f.label :password_confirmation, 'Confirm new password', class: 'label' %>
|
<%= f.label :password_confirmation, 'Confirm new password', class: 'label' %>
|
||||||
<%= f.password_field :password_confirmation, autocomplete: 'off', class: 'base-input' %>
|
<%= f.password_field :password_confirmation, autocomplete: 'off', class: 'base-input' %>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control">
|
<div class="form-control pt-2">
|
||||||
<%= f.button button_title(title: 'Update', disabled_with: 'Updating'), class: 'base-button' %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
<p class="text-2xl font-bold mt-8 mb-4">App URL</p>
|
|
||||||
<%= form_for @encrypted_config, url: update_app_url_settings_profile_index_path, method: :patch, html: { autocomplete: 'off', class: 'space-y-4' } do |f| %>
|
|
||||||
<div class="form-control">
|
|
||||||
<%= f.text_field :value, required: true, class: 'base-input' %>
|
|
||||||
</div>
|
|
||||||
<div class="form-control">
|
|
||||||
<%= f.button button_title(title: 'Update', disabled_with: 'Updating'), class: 'base-button' %>
|
<%= f.button button_title(title: 'Update', disabled_with: 'Updating'), class: 'base-button' %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -1 +1,18 @@
|
|||||||
Email has bee sent
|
<div class="max-w-md mx-auto px-2 mt-12 mb-4">
|
||||||
|
<div class="space-y-6 mx-auto">
|
||||||
|
<div class="space-y-6">
|
||||||
|
<div class="flex items-center justify-center">
|
||||||
|
<a href="/" class="flex items-center">
|
||||||
|
<div class="mr-3">
|
||||||
|
<%= render 'shared/logo', width: '50px', height: '50px' %>
|
||||||
|
</div>
|
||||||
|
<h1 class="text-5xl font-bold text-center">DocuSeal</h1>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="text-center text-4xl font-bold">
|
||||||
|
Email has been sent
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<%= render 'shared/attribution' %>
|
||||||
|
|||||||
@@ -14,17 +14,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<%= f.fields_for @user do |ff| %>
|
||||||
|
<div class="form-control">
|
||||||
|
<%= ff.label :email, class: 'label' %>
|
||||||
|
<%= ff.email_field :email, required: true, class: 'base-input' %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
<%= f.fields_for @account do |ff| %>
|
<%= f.fields_for @account do |ff| %>
|
||||||
|
<set-timezone data-input-id="_account_timezone"></set-timezone>
|
||||||
|
<%= ff.hidden_field :timezone %>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= ff.label :name, 'Company name', class: 'label' %>
|
<%= ff.label :name, 'Company name', class: 'label' %>
|
||||||
<%= ff.text_field :name, required: true, class: 'base-input' %>
|
<%= ff.text_field :name, required: true, class: 'base-input' %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= f.fields_for @user do |ff| %>
|
<%= f.fields_for @user do |ff| %>
|
||||||
<div class="form-control">
|
|
||||||
<%= ff.label :email, class: 'label' %>
|
|
||||||
<%= ff.email_field :email, required: true, class: 'base-input' %>
|
|
||||||
</div>
|
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<%= ff.label :password, class: 'label' %>
|
<%= ff.label :password, class: 'label' %>
|
||||||
<%= ff.password_field :password, required: true, placeholder: '************', class: 'base-input' %>
|
<%= ff.password_field :password, required: true, placeholder: '************', class: 'base-input' %>
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
<div class="card bg-base-200">
|
|
||||||
<div class="card-body text-center">
|
|
||||||
<div class="max-w-md mx-auto">
|
|
||||||
<p class="text-4xl font-semibold text-gray-700 mb-4">Nothing to display</p>
|
|
||||||
<p class="text-gray-500">We apologize, but currently there is no data available to be displayed. You can try adding new entries or refreshing the page to see if any data becomes available.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
<% if @pagy.pages > 1 %>
|
<% if @pagy.pages > 1 %>
|
||||||
<div class="flex my-6 justify-center md:justify-between">
|
<div class="flex my-6 justify-center md:justify-between">
|
||||||
<div class="hidden md:block text-sm">
|
<div class="hidden md:block text-sm">
|
||||||
<%= @pagy.from %>-<%= @pagy.to %> of <%= @pagy.count %> of <%= local_assigns[:items_name] || 'items' %>
|
<%= @pagy.from %>-<%= @pagy.to %> of <%= @pagy.count %> <%= local_assigns[:items_name] || 'items' %>
|
||||||
</div>
|
</div>
|
||||||
<div class="join">
|
<div class="join">
|
||||||
<% if @pagy.prev %>
|
<% if @pagy.prev %>
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
<li>
|
<li>
|
||||||
<%= link_to 'Profile', settings_profile_index_path, class: 'text-base hover:bg-base-300' %>
|
<%= link_to 'Profile', settings_profile_index_path, class: 'text-base hover:bg-base-300' %>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<%= link_to 'Account', settings_account_path, class: 'text-base hover:bg-base-300' %>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<%= link_to 'Email', settings_email_index_path, class: 'text-base hover:bg-base-300' %>
|
<%= link_to 'Email', settings_email_index_path, class: 'text-base hover:bg-base-300' %>
|
||||||
</li>
|
</li>
|
||||||
@@ -13,7 +16,7 @@
|
|||||||
<%= link_to 'Storage', settings_storage_index_path, class: 'text-base hover:bg-base-300' %>
|
<%= link_to 'Storage', settings_storage_index_path, class: 'text-base hover:bg-base-300' %>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<%= link_to 'eSign', settings_esign_index_path, class: 'text-base hover:bg-base-300' %>
|
<%= link_to 'Signature', settings_esign_index_path, class: 'text-base hover:bg-base-300' %>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<%= link_to 'Team', settings_users_path, class: 'text-base hover:bg-base-300' %>
|
<%= link_to 'Team', settings_users_path, class: 'text-base hover:bg-base-300' %>
|
||||||
|
|||||||
@@ -1,4 +1,37 @@
|
|||||||
<p>
|
<div class="max-w-md mx-auto px-2 mt-12 mb-4">
|
||||||
Form has been submitted already - thanks!
|
<div class="space-y-6 mx-auto">
|
||||||
</p>
|
<div class="space-y-6">
|
||||||
<%= button_to button_title(title: 'Send copy to Email', disabled_with: 'Sending'), send_submission_email_index_path, params: { template_slug: @template.slug, email: params[:email] }, form: { onsubmit: 'event.submitter.disabled = true' } %>
|
<div class="flex items-center justify-center">
|
||||||
|
<a href="/" class="flex items-center">
|
||||||
|
<div class="mr-3">
|
||||||
|
<%= render 'shared/logo', width: '50px', height: '50px' %>
|
||||||
|
</div>
|
||||||
|
<h1 class="text-5xl font-bold text-center">DocuSeal</h1>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center bg-base-300 rounded-xl p-4 mb-4">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="mr-3">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-10 h-10" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path d="M3 19c3.333 -2 5 -4 5 -6c0 -3 -1 -3 -2 -3s-2.032 1.085 -2 3c.034 2.048 1.658 2.877 2.5 4c1.5 2 2.5 2.5 3.5 1c.667 -1 1.167 -1.833 1.5 -2.5c1 2.333 2.333 3.5 4 3.5h2.5" />
|
||||||
|
<path d="M20 17v-12c0 -1.121 -.879 -2 -2 -2s-2 .879 -2 2v12l2 2l2 -2z" />
|
||||||
|
<path d="M16 7h4" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="text-lg font-bold mb-1"><%= @submitter.submission.template.name %></p>
|
||||||
|
<p class="text-sm">Signed on <%= l(@submitter.completed_at.to_date, format: :long, locale: @submitter.submission.template.account.locale) %></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-center text-2xl font-semibold">
|
||||||
|
Form has been submitter already
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<%= button_to button_title(title: 'Send copy to Email', disabled_with: 'Sending', icon: svg_icon('mail_forward', class: 'w-6 h-6')), send_submission_email_index_path, params: { submitter_slug: @submitter.slug }, form: { onsubmit: 'event.submitter.disabled = true' }, class: 'base-button w-full' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<%= render 'shared/attribution' %>
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
<h1 class="text-5xl font-bold text-center">DocuSeal</h1>
|
<h1 class="text-5xl font-bold text-center">DocuSeal</h1>
|
||||||
</a>
|
</a>
|
||||||
<p class="text-xl font-semibold text-center">You have been invited to submit the form</p>
|
<p class="text-xl font-semibold text-center">You have been invited to submit the form</p>
|
||||||
<div class="flex items-center bg-neutral rounded-xl p-4">
|
<div class="flex items-center bg-base-content/10 rounded-xl p-4">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="mr-3">
|
<div class="mr-3">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-10 h-10 text-gray-100 " width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-10 h-10" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
<path d="M3 19c3.333 -2 5 -4 5 -6c0 -3 -1 -3 -2 -3s-2.032 1.085 -2 3c.034 2.048 1.658 2.877 2.5 4c1.5 2 2.5 2.5 3.5 1c.667 -1 1.167 -1.833 1.5 -2.5c1 2.333 2.333 3.5 4 3.5h2.5" />
|
<path d="M3 19c3.333 -2 5 -4 5 -6c0 -3 -1 -3 -2 -3s-2.032 1.085 -2 3c.034 2.048 1.658 2.877 2.5 4c1.5 2 2.5 2.5 3.5 1c.667 -1 1.167 -1.833 1.5 -2.5c1 2.333 2.333 3.5 4 3.5h2.5" />
|
||||||
<path d="M20 17v-12c0 -1.121 -.879 -2 -2 -2s-2 .879 -2 2v12l2 2l2 -2z" />
|
<path d="M20 17v-12c0 -1.121 -.879 -2 -2 -2s-2 .879 -2 2v12l2 2l2 -2z" />
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p class="text-gray-100 font-bold mb-1"><%= @template.name %></p>
|
<p class="font-bold mb-1"><%= @template.name %></p>
|
||||||
<p class="text-sm text-gray-300">Invited by <%= @template.account.name %></p>
|
<p class="text-sm">Invited by <%= @template.account.name %></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,9 +2,6 @@
|
|||||||
<%= render 'shared/settings_nav' %>
|
<%= render 'shared/settings_nav' %>
|
||||||
<div class="flex-grow max-w-xl mx-auto">
|
<div class="flex-grow max-w-xl mx-auto">
|
||||||
<h1 class="text-4xl font-bold mb-4">Storage</h1>
|
<h1 class="text-4xl font-bold mb-4">Storage</h1>
|
||||||
<p class="mb-4">
|
|
||||||
Select files storage option (TODO)
|
|
||||||
</p>
|
|
||||||
<% value = @encrypted_config.value || { 'service' => 'disk' } %>
|
<% value = @encrypted_config.value || { 'service' => 'disk' } %>
|
||||||
<% configs = value['configs'] || {} %>
|
<% configs = value['configs'] || {} %>
|
||||||
<%= form_for @encrypted_config, url: settings_storage_index_path, method: :post, html: { autocomplete: 'off', class: 'w-full' } do |f| %>
|
<%= form_for @encrypted_config, url: settings_storage_index_path, method: :post, html: { autocomplete: 'off', class: 'w-full' } do |f| %>
|
||||||
@@ -29,10 +26,10 @@
|
|||||||
<disable-hidden id="aws_s3" class="block my-4 space-y-4 <%= 'hidden' if value['service'] != 'aws_s3' %>">
|
<disable-hidden id="aws_s3" class="block my-4 space-y-4 <%= 'hidden' if value['service'] != 'aws_s3' %>">
|
||||||
<%= render 'aws_form', f:, configs:, value: %>
|
<%= render 'aws_form', f:, configs:, value: %>
|
||||||
</disable-hidden>
|
</disable-hidden>
|
||||||
<disable-hidden id="google" class="block mt-4 space-y-4 mb-8 <%= 'hidden' if value['service'] != 'google' %>">
|
<disable-hidden id="google" class="block mt-4 space-y-4 mb-6 <%= 'hidden' if value['service'] != 'google' %>">
|
||||||
<%= render 'google_cloud_form', f:, configs:, value: %>
|
<%= render 'google_cloud_form', f:, configs:, value: %>
|
||||||
</disable-hidden>
|
</disable-hidden>
|
||||||
<disable-hidden id="azure" class="block mt-4 space-y-4 mb-8 <%= 'hidden' if value['service'] != 'azure' %>">
|
<disable-hidden id="azure" class="block mt-4 space-y-4 mb-6 <%= 'hidden' if value['service'] != 'azure' %>">
|
||||||
<%= render 'azure_form', f:, configs:, value: %>
|
<%= render 'azure_form', f:, configs:, value: %>
|
||||||
</disable-hidden>
|
</disable-hidden>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<% elsif field['type'] == 'date' %>
|
<% elsif field['type'] == 'date' %>
|
||||||
<div class="flex items-center px-0.5">
|
<div class="flex items-center px-0.5">
|
||||||
<%= l(Date.parse(value)) %>
|
<%= l(Date.parse(value), format: :long, locale: local_assigns[:locale]) %>
|
||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
<div class="flex items-center px-0.5">
|
<div class="flex items-center px-0.5">
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<div style="max-width: 1600px" class="mx-auto pl-4">
|
<div style="max-width: 1600px" class="mx-auto pl-4">
|
||||||
<div class="flex justify-between py-1.5 items-center pr-4">
|
<div class="flex justify-between py-1.5 items-center pr-4">
|
||||||
<div class="flex space-x-3">
|
<a href="<%= template_path(@submission.template) %>" class="flex space-x-3">
|
||||||
<a href="/"><%= render 'shared/logo' %></a>
|
<span><%= render 'shared/logo' %></span>
|
||||||
<span class="text-3xl font-semibold focus:text-clip"><%= @submission.template.name %></span>
|
<span class="text-3xl font-semibold focus:text-clip"><%= @submission.template.name %></span>
|
||||||
</div>
|
</a>
|
||||||
<div class="space-x-3 flex items-center">
|
<div class="space-x-3 flex items-center">
|
||||||
<% if last_submitter = @submission.submitters.select(&:completed_at?).max_by(&:completed_at) %>
|
<% if last_submitter = @submission.submitters.select(&:completed_at?).max_by(&:completed_at) %>
|
||||||
<download-button data-src="<%= submitter_download_index_path(last_submitter.slug) %>" class="base-button">
|
<download-button data-src="<%= submitter_download_index_path(last_submitter.slug) %>" class="base-button">
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
<% fields_index.dig(document.uuid, index)&.each do |(area, field)| %>
|
<% fields_index.dig(document.uuid, index)&.each do |(area, field)| %>
|
||||||
<% value = values[field['uuid']] %>
|
<% value = values[field['uuid']] %>
|
||||||
<% next if value.blank? %>
|
<% next if value.blank? %>
|
||||||
<%= render 'submissions/value', area:, field:, attachments_index:, value: %>
|
<%= render 'submissions/value', area:, field:, attachments_index:, value:, locale: current_account.locale %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<% if submitter && !submitter.completed_at? %>
|
<% if submitter && !submitter.completed_at? %>
|
||||||
<div class="mt-2 mb-1">
|
<div class="mt-2 mb-1">
|
||||||
<a class="btn btn-xs btn-primary w-full" target="_blank" href="<%= submit_form_url(slug: submitter.slug) %>">
|
<a class="btn btn-sm btn-primary w-full" target="_blank" href="<%= submit_form_url(slug: submitter.slug) %>">
|
||||||
Submit Form
|
Submit Form
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
<% elsif field['type'] == 'checkbox' %>
|
<% elsif field['type'] == 'checkbox' %>
|
||||||
<%= svg_icon('check', class: 'w-6 h-6') %>
|
<%= svg_icon('check', class: 'w-6 h-6') %>
|
||||||
<% elsif field['type'] == 'date' %>
|
<% elsif field['type'] == 'date' %>
|
||||||
<%= l(Date.parse(value)) %>
|
<%= l(Date.parse(value), locale: current_account.locale, format: :long) %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= Array.wrap(value).join(', ') %>
|
<%= Array.wrap(value).join(', ') %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<div class="flex items-center bg-base-300 rounded-xl p-4 mb-4">
|
<div class="flex items-center bg-base-300 rounded-xl p-4 mb-4">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="mr-3">
|
<div class="mr-3">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="w-10 h-10 text-gray-700 " width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
<svg xmlns="http://www.w3.org/2000/svg" class="w-10 h-10" width="44" height="44" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
<path d="M3 19c3.333 -2 5 -4 5 -6c0 -3 -1 -3 -2 -3s-2.032 1.085 -2 3c.034 2.048 1.658 2.877 2.5 4c1.5 2 2.5 2.5 3.5 1c.667 -1 1.167 -1.833 1.5 -2.5c1 2.333 2.333 3.5 4 3.5h2.5" />
|
<path d="M3 19c3.333 -2 5 -4 5 -6c0 -3 -1 -3 -2 -3s-2.032 1.085 -2 3c.034 2.048 1.658 2.877 2.5 4c1.5 2 2.5 2.5 3.5 1c.667 -1 1.167 -1.833 1.5 -2.5c1 2.333 2.333 3.5 4 3.5h2.5" />
|
||||||
<path d="M20 17v-12c0 -1.121 -.879 -2 -2 -2s-2 .879 -2 2v12l2 2l2 -2z" />
|
<path d="M20 17v-12c0 -1.121 -.879 -2 -2 -2s-2 .879 -2 2v12l2 2l2 -2z" />
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p class="text-lg text-gray-700 font-bold mb-1"><%= @submitter.submission.template.name %></p>
|
<p class="text-lg font-bold mb-1"><%= @submitter.submission.template.name %></p>
|
||||||
<p class="text-sm text-gray-500">Signed on <%= l(@submitter.completed_at.to_date, format: :long) %></p>
|
<p class="text-sm">Signed on <%= l(@submitter.completed_at.to_date, format: :long, locale: @submitter.submission.template.account.locale) %></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<% fields_index = Templates.build_field_areas_index(@submitter.submission.template) %>
|
<% fields_index = Templates.build_field_areas_index(@submitter.submission.template) %>
|
||||||
<% values = @submitter.submission.submitters.reduce({}) { |acc, sub| acc.merge(sub.values) } %>
|
<% values = @submitter.submission.submitters.where.not(id: @submitter.id).reduce({}) { |acc, sub| acc.merge(sub.values) } %>
|
||||||
<% attachments_index = ActiveStorage::Attachment.where(record: @submitter.submission.submitters, name: :attachments).preload(:blob).index_by(&:uuid) %>
|
<% attachments_index = ActiveStorage::Attachment.where(record: @submitter.submission.submitters, name: :attachments).preload(:blob).index_by(&:uuid) %>
|
||||||
<div class="mx-auto block pb-72" style="max-width: 1000px">
|
<div class="mx-auto block pb-72" style="max-width: 1000px">
|
||||||
<div class="mt-4 flex">
|
<div class="mt-4 flex">
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
<% fields_index.dig(document.uuid, index)&.each do |(area, field)| %>
|
<% fields_index.dig(document.uuid, index)&.each do |(area, field)| %>
|
||||||
<% value = values[field['uuid']] %>
|
<% value = values[field['uuid']] %>
|
||||||
<% next if value.blank? %>
|
<% next if value.blank? %>
|
||||||
<%= render 'submissions/value', area:, field:, attachments_index:, value: %>
|
<%= render 'submissions/value', area:, field:, attachments_index:, value:, locale: @submitter.submission.template.account.locale %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
<div class="fixed bottom-0 w-full h-0 z-20">
|
<div class="fixed bottom-0 w-full h-0 z-20">
|
||||||
<div class="mx-auto" style="max-width: 1000px">
|
<div class="mx-auto" style="max-width: 1000px">
|
||||||
<div class="relative md:mx-32">
|
<div class="relative md:mx-32">
|
||||||
<div class="shadow-md bg-base-100 absolute bottom-0 md:bottom-4 w-full border border-base-200 p-4 rounded">
|
<div class="shadow-md bg-base-100 absolute bottom-0 md:bottom-4 w-full border border-base-200 border p-4 rounded">
|
||||||
<submission-form data-submitter-uuid="<%= @submitter.uuid %>" data-submitter-slug="<%= @submitter.slug %>" data-attachments="<%= attachments_index.values.select { |e| e.record_id == @submitter.id }.to_json(only: %i[uuid], methods: %i[url filename content_type]) %>" data-fields="<%= @submitter.submission.template.fields.select { |f| f['submitter_uuid'] == @submitter.uuid }.to_json %>" data-values="<%= @submitter.values.to_json %>" data-authenticity-token="<%= form_authenticity_token %>"></submission-form>
|
<submission-form data-submitter-uuid="<%= @submitter.uuid %>" data-submitter-slug="<%= @submitter.slug %>" data-attachments="<%= attachments_index.values.select { |e| e.record_id == @submitter.id }.to_json(only: %i[uuid], methods: %i[url filename content_type]) %>" data-fields="<%= @submitter.submission.template.fields.select { |f| f['submitter_uuid'] == @submitter.uuid }.to_json %>" data-values="<%= @submitter.values.to_json %>" data-authenticity-token="<%= form_authenticity_token %>"></submission-form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,18 +16,22 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between mb-4 items-end">
|
<% if !@pagy.count.zero? || @template.submitters.to_a.size == 1 %>
|
||||||
<p class="text-3xl font-bold">Submissions</p>
|
<div class="flex justify-between mb-4 items-end">
|
||||||
<div class="flex space-x-2">
|
<p class="text-3xl font-bold">Submissions</p>
|
||||||
<% if @template.submitters.to_a.size == 1 %>
|
<div class="flex space-x-2">
|
||||||
<%= render 'shared/clipboard_copy', text: start_form_url(slug: @template.slug), class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy Share Link', copied_title: 'Copied to Clipboard' %>
|
<% if @template.submitters.to_a.size == 1 %>
|
||||||
<% end %>
|
<%= render 'shared/clipboard_copy', text: start_form_url(slug: @template.slug), class: 'base-button', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy Share Link', copied_title: 'Copied to Clipboard' %>
|
||||||
<%= link_to new_template_submission_path(@template), class: 'btn btn-primary text-base', data: { turbo_frame: 'modal' } do %>
|
<% end %>
|
||||||
<%= svg_icon('plus', class: 'w-6 h-6 stroke-2') %>
|
<% unless @pagy.count.zero? %>
|
||||||
<span class="hidden md:block">Add Recipients</span>
|
<%= link_to new_template_submission_path(@template), class: 'btn btn-primary text-base', data: { turbo_frame: 'modal' } do %>
|
||||||
<% end %>
|
<%= svg_icon('plus', class: 'w-6 h-6 stroke-2') %>
|
||||||
|
<span class="hidden md:block">Add Recipients</span>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<% end %>
|
||||||
<% status_badges = { 'awaiting' => 'badge-info', 'sent' => 'badge-info', 'completed' => 'badge-success', 'opened' => 'badge-warning' } %>
|
<% status_badges = { 'awaiting' => 'badge-info', 'sent' => 'badge-info', 'completed' => 'badge-success', 'opened' => 'badge-warning' } %>
|
||||||
<% if @submissions.present? %>
|
<% if @submissions.present? %>
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
@@ -46,9 +50,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex space-x-2 items-center">
|
<div class="flex space-x-2 items-center">
|
||||||
<span class="badge <%= status_badges[submitter.status] %> w-32 badge-lg btn-sm uppercase text-sm font-medium border-1">
|
<div class="tooltip flex" data-tip="<%= l(submitter.status_event_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %>">
|
||||||
<%= submitter.status %>
|
<span class="badge <%= status_badges[submitter.status] %> w-32 badge-lg btn-sm uppercase text-sm font-medium border-1">
|
||||||
</span>
|
<%= submitter.status %>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<% if submitter.completed_at? %>
|
<% if submitter.completed_at? %>
|
||||||
<form onsubmit="event.preventDefault()">
|
<form onsubmit="event.preventDefault()">
|
||||||
<button onclick="event.stopPropagation()">
|
<button onclick="event.stopPropagation()">
|
||||||
@@ -65,7 +71,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: submission.submitters.first.slug), class: 'btn btn-sm btn-neutral text-white w-36', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy Link' %>
|
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: submission.submitters.first.slug), class: 'btn btn-sm btn-neutral text-white w-36 flex', icon_class: 'w-6 h-6 text-white', copy_title: 'Copy Link' %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= button_to submitter.completed_at? ? 'Archive' : 'Remove', submission_path(submission), class: 'btn btn-outline btn-sm w-28', title: 'Delete', method: :delete, data: { turbo_confirm: 'Are you sure?' }, onclick: 'event.stopPropagation()' %>
|
<%= button_to submitter.completed_at? ? 'Archive' : 'Remove', submission_path(submission), class: 'btn btn-outline btn-sm w-28', title: 'Delete', method: :delete, data: { turbo_confirm: 'Are you sure?' }, onclick: 'event.stopPropagation()' %>
|
||||||
</div>
|
</div>
|
||||||
@@ -82,10 +88,12 @@
|
|||||||
</span>
|
</span>
|
||||||
<% unless submission.submitters.all?(&:completed_at?) %>
|
<% unless submission.submitters.all?(&:completed_at?) %>
|
||||||
<div class="flex items-center space-x-3">
|
<div class="flex items-center space-x-3">
|
||||||
<span class="badge w-24 <%= status_badges[submitter.status] %> btn-xs uppercase text-xs font-medium border-1">
|
<div class="tooltip flex" data-tip="<%= l(submitter.status_event_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %>">
|
||||||
<%= submitter.status %>
|
<span class="badge w-24 <%= status_badges[submitter.status] %> btn-xs uppercase text-xs font-medium border-1">
|
||||||
</span>
|
<%= submitter.status %>
|
||||||
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: submitter.slug), class: 'btn btn-xs text-xs btn-neutral text-white w-32', icon_class: 'w-4 h-4 text-white', copy_title: 'Copy Link' %>
|
</span>
|
||||||
|
</div>
|
||||||
|
<%= render 'shared/clipboard_copy', text: submit_form_url(slug: submitter.slug), class: 'btn btn-xs text-xs btn-neutral text-white w-32 flex', icon_class: 'w-4 h-4 text-white', copy_title: 'Copy Link' %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
@@ -93,9 +101,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex space-x-2 items-center">
|
<div class="flex space-x-2 items-center">
|
||||||
<% if submission.submitters.all?(&:completed_at?) %>
|
<% if submission.submitters.all?(&:completed_at?) %>
|
||||||
<span class="badge <%= status_badges[submitter.status] %> w-32 badge-lg btn-sm uppercase text-sm font-medium border-1">
|
<div class="tooltip flex" data-tip="<%= l(submitter.status_event_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) %>">
|
||||||
<%= submitter.status %>
|
<span class="badge <%= status_badges[submitter.status] %> w-32 badge-lg btn-sm uppercase text-sm font-medium border-1">
|
||||||
</span>
|
<%= submitter.status %>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<form onsubmit="event.preventDefault()">
|
<form onsubmit="event.preventDefault()">
|
||||||
<button onclick="event.stopPropagation()">
|
<button onclick="event.stopPropagation()">
|
||||||
<download-button data-src="<%= submitter_download_index_path(submission.submitters.select(&:completed_at?).max_by(&:completed_at).slug) %>" class="btn btn-sm btn-neutral text-white w-36">
|
<download-button data-src="<%= submitter_download_index_path(submission.submitters.select(&:completed_at?).max_by(&:completed_at).slug) %>" class="btn btn-sm btn-neutral text-white w-36">
|
||||||
@@ -117,7 +127,18 @@
|
|||||||
</a>
|
</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<%= render 'shared/pagination', pagy: @pagy, items_name: 'Submissions' %>
|
<%= render 'shared/pagination', pagy: @pagy, items_name: 'submissions' %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= render 'shared/no_data_banner' %>
|
<div class="card bg-base-200">
|
||||||
|
<div class="card-body text-center py-16">
|
||||||
|
<div class="max-w-md mx-auto">
|
||||||
|
<p class="text-3xl font-bold text-base-content mb-4">There are no Submissions yet</p>
|
||||||
|
<p class="text-gray-600">Send an invitation to fill and submit the documents via email</p>
|
||||||
|
<%= link_to new_template_submission_path(@template), class: 'base-button mt-6', data: { turbo_frame: 'modal' } do %>
|
||||||
|
<%= svg_icon('plus', class: 'w-6 h-6 stroke-2') %>
|
||||||
|
<span class="hidden md:block">Add Recipients</span>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<%= f.password_field :password, required: user.new_record?, class: 'base-input' %>
|
<%= f.password_field :password, required: user.new_record?, class: 'base-input' %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control">
|
<div class="form-control pt-2">
|
||||||
<%= f.button button_title, class: 'base-button' %>
|
<%= f.button button_title, class: 'base-button' %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<%= user.last_sign_in_at ? l(user.last_sign_in_at, format: :short) : '-' %>
|
<%= user.last_sign_in_at ? l(user.last_sign_in_at.in_time_zone(current_account.timezone), format: :short, locale: current_account.locale) : '-' %>
|
||||||
</td>
|
</td>
|
||||||
<td class="flex items-center space-x-2 justify-end">
|
<td class="flex items-center space-x-2 justify-end">
|
||||||
<%= link_to edit_user_path(user), class: 'btn btn-outline btn-xs', title: 'Edit', data: { turbo_frame: 'modal' } do %>
|
<%= link_to edit_user_path(user), class: 'btn btn-outline btn-xs', title: 'Edit', data: { turbo_frame: 'modal' } do %>
|
||||||
@@ -58,6 +58,6 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<%= render 'shared/pagination', pagy: @pagy, items_name: 'Users' %>
|
<%= render 'shared/pagination', pagy: @pagy, items_name: 'users' %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ module DocuSeal
|
|||||||
|
|
||||||
config.active_storage.routes_prefix = ''
|
config.active_storage.routes_prefix = ''
|
||||||
|
|
||||||
|
config.i18n.available_locales = %i[en en-US en-GB es-ES pt-PT de-DE]
|
||||||
|
config.i18n.fallbacks = [:en]
|
||||||
|
|
||||||
config.action_view.frozen_string_literal = true
|
config.action_view.frozen_string_literal = true
|
||||||
|
|
||||||
config.middleware.insert_before ActionDispatch::Static, Rack::Deflater
|
config.middleware.insert_before ActionDispatch::Static, Rack::Deflater
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ if ENV['RAILS_ENV'] == 'production' && ENV['SECRET_KEY_BASE'].to_s.empty?
|
|||||||
require 'dotenv'
|
require 'dotenv'
|
||||||
require 'securerandom'
|
require 'securerandom'
|
||||||
|
|
||||||
dotenv_path = './docuseal.env'
|
dotenv_path = "#{ENV.fetch('WORKDIR', '.')}/docuseal.env"
|
||||||
|
|
||||||
unless File.exist?(dotenv_path)
|
unless File.exist?(dotenv_path)
|
||||||
default_env = <<~TEXT
|
default_env = <<~TEXT
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ Rails.application.routes.draw do
|
|||||||
resources :email, only: %i[index create], controller: 'email_settings'
|
resources :email, only: %i[index create], controller: 'email_settings'
|
||||||
resources :esign, only: %i[index create], controller: 'esign_settings'
|
resources :esign, only: %i[index create], controller: 'esign_settings'
|
||||||
resources :users, only: %i[index]
|
resources :users, only: %i[index]
|
||||||
|
resource :account, only: %i[show update]
|
||||||
resources :profile, only: %i[index] do
|
resources :profile, only: %i[index] do
|
||||||
collection do
|
collection do
|
||||||
patch :update_contact
|
patch :update_contact
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ class CreateAccounts < ActiveRecord::Migration[7.0]
|
|||||||
def change
|
def change
|
||||||
create_table :accounts do |t|
|
create_table :accounts do |t|
|
||||||
t.string :name, null: false
|
t.string :name, null: false
|
||||||
|
t.string :timezone, null: false
|
||||||
|
t.string :locale, null: false
|
||||||
|
|
||||||
t.timestamps
|
t.timestamps
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_06_12_182744) do
|
|||||||
|
|
||||||
create_table "accounts", force: :cascade do |t|
|
create_table "accounts", force: :cascade do |t|
|
||||||
t.string "name", null: false
|
t.string "name", null: false
|
||||||
|
t.string "timezone", null: false
|
||||||
|
t.string "locale", null: false
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Accounts
|
||||||
|
module_function
|
||||||
|
|
||||||
|
def normalize_timezone(timezone)
|
||||||
|
tzinfo = TZInfo::Timezone.get(ActiveSupport::TimeZone::MAPPING[timezone] || timezone)
|
||||||
|
|
||||||
|
::ActiveSupport::TimeZone.all.find { |e| e.tzinfo == tzinfo }&.name || timezone
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -135,7 +135,7 @@ module Submissions
|
|||||||
height - (area['y'] * height))
|
height - (area['y'] * height))
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
value = I18n.l(Date.parse(value)) if field['type'] == 'date'
|
value = I18n.l(Date.parse(value), format: :long) if field['type'] == 'date'
|
||||||
|
|
||||||
text = HexaPDF::Layout::TextFragment.create(Array.wrap(value).join(', '), font: pdf.fonts.add(FONT_NAME),
|
text = HexaPDF::Layout::TextFragment.create(Array.wrap(value).join(', '), font: pdf.fonts.add(FONT_NAME),
|
||||||
font_size: FONT_SIZE)
|
font_size: FONT_SIZE)
|
||||||
|
|||||||
@@ -8,6 +8,6 @@ module.exports = {
|
|||||||
'./app/views/start_form/**/*.erb',
|
'./app/views/start_form/**/*.erb',
|
||||||
'./app/views/shared/_button_title.html.erb',
|
'./app/views/shared/_button_title.html.erb',
|
||||||
'./app/views/shared/_attribution.html.erb',
|
'./app/views/shared/_attribution.html.erb',
|
||||||
'./app/views/send_submission_copy/**/*.erb'
|
'./app/views/send_submission_email/**/*.erb'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user