mirror of https://github.com/docusealco/docuseal
				
				
				
			
							parent
							
								
									f8712a9da9
								
							
						
					
					
						commit
						380f553a17
					
				| @ -0,0 +1,16 @@ | |||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | module Api | ||||||
|  |   class TemplateFoldersAutocompleteController < ApiBaseController | ||||||
|  |     load_and_authorize_resource :template_folder, parent: false | ||||||
|  | 
 | ||||||
|  |     LIMIT = 100 | ||||||
|  | 
 | ||||||
|  |     def index | ||||||
|  |       template_folders = @template_folders.joins(:templates).where(templates: { deleted_at: nil }).distinct | ||||||
|  |       template_folders = TemplateFolders.search(template_folders, params[:q]).limit(LIMIT) | ||||||
|  | 
 | ||||||
|  |       render json: template_folders.as_json(only: %i[name deleted_at]) | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | end | ||||||
| @ -0,0 +1,29 @@ | |||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class TemplateFoldersController < ApplicationController | ||||||
|  |   load_and_authorize_resource :template_folder | ||||||
|  | 
 | ||||||
|  |   def show | ||||||
|  |     @templates = @template_folder.templates.active.preload(:author).order(id: :desc) | ||||||
|  |     @templates = Templates.search(@templates, params[:q]) | ||||||
|  | 
 | ||||||
|  |     @pagy, @templates = pagy(@templates, items: 12) | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def edit; end | ||||||
|  | 
 | ||||||
|  |   def update | ||||||
|  |     if @template_folder != current_account.default_template_folder && | ||||||
|  |        @template_folder.update(template_folder_params) | ||||||
|  |       redirect_to folder_path(@template_folder), notice: 'Folder name has been updated' | ||||||
|  |     else | ||||||
|  |       redirect_to folder_path(@template_folder), alert: 'Unable to rename folder' | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   private | ||||||
|  | 
 | ||||||
|  |   def template_folder_params | ||||||
|  |     params.require(:template_folder).permit(:name) | ||||||
|  |   end | ||||||
|  | end | ||||||
| @ -0,0 +1,23 @@ | |||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | class TemplatesFoldersController < ApplicationController | ||||||
|  |   load_and_authorize_resource :template | ||||||
|  | 
 | ||||||
|  |   def edit; end | ||||||
|  | 
 | ||||||
|  |   def update | ||||||
|  |     @template.folder = TemplateFolders.find_or_create_by_name(current_user, params[:name]) | ||||||
|  | 
 | ||||||
|  |     if @template.save | ||||||
|  |       redirect_back(fallback_location: template_path(@template), notice: 'Document template has been moved') | ||||||
|  |     else | ||||||
|  |       redirect_back(fallback_location: template_path(@template), notice: 'Unable to move template into folder') | ||||||
|  |     end | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   private | ||||||
|  | 
 | ||||||
|  |   def template_folder_params | ||||||
|  |     params.require(:template_folder).permit(:name) | ||||||
|  |   end | ||||||
|  | end | ||||||
| @ -0,0 +1,43 @@ | |||||||
|  | import autocomplete from 'autocompleter' | ||||||
|  | 
 | ||||||
|  | export default class extends HTMLElement { | ||||||
|  |   connectedCallback () { | ||||||
|  |     autocomplete({ | ||||||
|  |       input: this.input, | ||||||
|  |       preventSubmit: this.dataset.submitOnSelect === 'true' ? 0 : 1, | ||||||
|  |       minLength: 0, | ||||||
|  |       showOnFocus: true, | ||||||
|  |       onSelect: this.onSelect, | ||||||
|  |       render: this.render, | ||||||
|  |       fetch: this.fetch | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   onSelect = (item) => { | ||||||
|  |     this.input.value = item.name | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   fetch = (text, resolve) => { | ||||||
|  |     const queryParams = new URLSearchParams({ q: text }) | ||||||
|  | 
 | ||||||
|  |     fetch('/api/template_folders_autocomplete?' + queryParams).then(async (resp) => { | ||||||
|  |       const items = await resp.json() | ||||||
|  | 
 | ||||||
|  |       resolve(items) | ||||||
|  |     }).catch(() => { | ||||||
|  |       resolve([]) | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   render = (item) => { | ||||||
|  |     const div = document.createElement('div') | ||||||
|  | 
 | ||||||
|  |     div.textContent = item.name | ||||||
|  | 
 | ||||||
|  |     return div | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get input () { | ||||||
|  |     return this.querySelector('input') | ||||||
|  |   } | ||||||
|  | } | ||||||
| After Width: | Height: | Size: 354 B | 
| After Width: | Height: | Size: 391 B | 
| After Width: | Height: | Size: 448 B | 
| After Width: | Height: | Size: 469 B | 
| @ -0,0 +1,12 @@ | |||||||
|  | <% is_long = folder.name.size > 32 %> | ||||||
|  | <a href="<%= folder_path(folder) %>" class="flex h-full flex-col justify-between rounded-2xl py-5 px-6 w-full bg-base-200"> | ||||||
|  |   <% if !is_long %> | ||||||
|  |     <%= svg_icon('folder', class: 'w-6 h-6') %> | ||||||
|  |   <% end %> | ||||||
|  |   <div class="text-lg font-semibold mt-1" style="overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: <%= is_long ? 2 : 1 %>;"> | ||||||
|  |     <% if is_long %> | ||||||
|  |       <%= svg_icon('folder', class: 'w-6 h-6 inline') %> | ||||||
|  |     <% end %> | ||||||
|  |     <%= folder.name %> | ||||||
|  |   </div> | ||||||
|  | </a> | ||||||
| @ -0,0 +1,10 @@ | |||||||
|  | <%= render 'shared/turbo_modal', title: 'Rename Folder' do %> | ||||||
|  |   <%= form_for @template_folder, url: folder_path(@template_folder), data: { turbo_frame: :_top }, html: { autocomplete: :off } do |f| %> | ||||||
|  |     <div class="form-control my-6"> | ||||||
|  |       <%= f.text_field :name, required: true, placeholder: 'Folder Name...', class: 'base-input w-full', autofocus: true %> | ||||||
|  |     </div> | ||||||
|  |     <div class="form-control"> | ||||||
|  |       <%= f.button button_title(title: 'Rename', disabled_with: 'Saving'), class: 'base-button' %> | ||||||
|  |     </div> | ||||||
|  |   <% end %> | ||||||
|  | <% end %> | ||||||
| @ -0,0 +1,45 @@ | |||||||
|  | <div> | ||||||
|  |   <%= link_to root_path do %> | ||||||
|  |     ← | ||||||
|  |     <span>Home</span> | ||||||
|  |   <% end %> | ||||||
|  | </div> | ||||||
|  | <div class="flex justify-between mb-4 items-center"> | ||||||
|  |   <h1 class="text-4xl font-bold flex items-center space-x-2"> | ||||||
|  |     <%= svg_icon('folder', class: 'w-9 h-9 flex-shrink-0') %> | ||||||
|  |     <span class="peer"> | ||||||
|  |       <%= @template_folder.name %> | ||||||
|  |     </span> | ||||||
|  |     <% if can?(:update, @template_folder) && @template_folder.name != TemplateFolder::DEFAULT_NAME %> | ||||||
|  |       <span class="pl-1 opacity-0 hover:opacity-100 peer-hover:opacity-100"> | ||||||
|  |         <a href="<%= edit_folder_path(@template_folder) %>" data-turbo-frame="modal"> | ||||||
|  |           <%= svg_icon('pencil', class: 'w-7 h-7') %> | ||||||
|  |         </a> | ||||||
|  |       </span> | ||||||
|  |     <% end %> | ||||||
|  |   </h1> | ||||||
|  |   <div class="flex space-x-2"> | ||||||
|  |     <% if params[:q].present? || @pagy.pages > 1 %> | ||||||
|  |       <%= render 'shared/search_input' %> | ||||||
|  |     <% end %> | ||||||
|  |     <% if can?(:create, ::Template) %> | ||||||
|  |       <%= render 'templates/upload_button', folder_name: @template_folder.name %> | ||||||
|  |       <%= link_to new_template_path(folder_name: @template_folder.name), class: 'btn btn-primary text-base btn-md gap-2', data: { turbo_frame: :modal } do %> | ||||||
|  |         <%= svg_icon('plus', class: 'w-6 h-6 stroke-2') %> | ||||||
|  |         <span class="hidden md:block">Create</span> | ||||||
|  |       <% end %> | ||||||
|  |     <% end %> | ||||||
|  |   </div> | ||||||
|  | </div> | ||||||
|  | <% if @pagy.count > 0 %> | ||||||
|  |   <div class="grid gap-4 md:grid-cols-3"> | ||||||
|  |     <%= render partial: 'templates/template', collection: @templates %> | ||||||
|  |   </div> | ||||||
|  |   <%= render 'shared/pagination', pagy: @pagy, items_name: 'templates' %> | ||||||
|  | <% elsif params[:q].present? %> | ||||||
|  |   <div class="text-center"> | ||||||
|  |     <div class="mt-16 text-3xl font-semibold"> | ||||||
|  |       Templates not Found | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | <% end %> | ||||||
| @ -0,0 +1,12 @@ | |||||||
|  | <%= render 'shared/turbo_modal', title: 'Move Into Folder' do %> | ||||||
|  |   <%= form_for '', url: template_folder_path(@template), method: :put, data: { turbo_frame: :_top }, html: { autocomplete: :off } do |f| %> | ||||||
|  |     <div class="form-control my-6"> | ||||||
|  |       <folder-autocomplete class="block" data-submit-on-select="true"> | ||||||
|  |         <%= f.text_field :name, required: true, placeholder: 'New Folder Name...', class: 'base-input w-full', autofocus: true %> | ||||||
|  |       </folder-autocomplete> | ||||||
|  |     </div> | ||||||
|  |     <div class="form-control"> | ||||||
|  |       <%= f.button button_title(title: 'Move', disabled_with: 'Moving'), class: 'base-button' %> | ||||||
|  |     </div> | ||||||
|  |   <% end %> | ||||||
|  | <% end %> | ||||||
| @ -0,0 +1,17 @@ | |||||||
|  | # frozen_string_literal: true | ||||||
|  | 
 | ||||||
|  | module TemplateFolders | ||||||
|  |   module_function | ||||||
|  | 
 | ||||||
|  |   def search(folders, keyword) | ||||||
|  |     return folders if keyword.blank? | ||||||
|  | 
 | ||||||
|  |     folders.where(TemplateFolder.arel_table[:name].lower.matches("%#{keyword.downcase}%")) | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|  |   def find_or_create_by_name(author, name) | ||||||
|  |     return author.account.default_template_folder if name.blank? || name == TemplateFolder::DEFAULT_NAME | ||||||
|  | 
 | ||||||
|  |     author.account.template_folders.create_with(author:, account: author.account).find_or_create_by(name:) | ||||||
|  |   end | ||||||
|  | end | ||||||
					Loading…
					
					
				
		Reference in new issue