diff --git a/app/assets/javascripts/label_templates/label_templates_datatable.js b/app/assets/javascripts/label_templates/label_templates_datatable.js index 004ea4220..1446ef747 100644 --- a/app/assets/javascripts/label_templates/label_templates_datatable.js +++ b/app/assets/javascripts/label_templates/label_templates_datatable.js @@ -23,7 +23,11 @@ } function renderNameHTML(data, type, row) { - return `${data.icon_url}${data.name}`; + return `${data.icon_url}${data.name}`; } function addAttributesToRow(row, data) { @@ -43,11 +47,9 @@ }); } - function initEditButton() { - $('#editLabelTemplate').on('click', function() { - if (rowsSelected.length === 1) { - window.open(editUrl, '_blank'); - } + function initCreateButton() { + $('#newLabelTemplate').on('click', function() { + $.post(this.dataset.url); }); } @@ -249,7 +251,7 @@ let toolBar = $($('#labelTemplatesToolbar').html()); $('.label-buttons-container').html(toolBar); - initEditButton(); + initCreateButton(); initSetDefaultButton(); initDuplicateButton(); initDeleteModal(); diff --git a/app/assets/stylesheets/label_templates/show.scss b/app/assets/stylesheets/label_templates/show.scss new file mode 100644 index 000000000..6b48c9386 --- /dev/null +++ b/app/assets/stylesheets/label_templates/show.scss @@ -0,0 +1,89 @@ +// scss-lint:disable SelectorDepth NestingDepth ImportantRule + +.label-templates-show { + .title-row { + height: unset !important; + + .label-template-icon { + flex-shrink: 0; + margin-bottom: auto; + margin-right: 5px; + margin-top: 13px; + width: 32px; + } + + .sci-inline-edit { + @include font-h1; + flex-grow: 1; + max-width: calc(100% - 50px); + } + } + + .template-descripiton { + @include font-button; + margin: 1em 0; + + .title { + font-weight: bold; + } + } + + .label-template-container { + display: flex; + + .title { + font-weight: bold; + } + + .label-edit-container { + flex-basis: 60%; + padding-right: 1em; + + .button-container { + display: flex; + + .refresh-preview { + margin-right: auto; + } + + .save-template { + margin-left: .25em; + } + } + } + + .label-preview-container { + flex-basis: 40%; + padding-left: 1em; + } + } + + .label-view-container { + cursor: pointer; + padding: .5em; + position: relative; + white-space: pre; + + .fa-pen { + display: none; + padding: 1em; + position: absolute; + right: 0; + top: 0; + } + + &:hover { + background-color: $color-concrete; + + .fa-pen { + display: inline-block; + } + } + } + + .label-textarea { + min-height: 240px; + padding: .5em; + width: 100%; + } +} diff --git a/app/assets/stylesheets/shared/inline_edit.scss b/app/assets/stylesheets/shared/inline_edit.scss index 145f5993c..84e0d86e7 100644 --- a/app/assets/stylesheets/shared/inline_edit.scss +++ b/app/assets/stylesheets/shared/inline_edit.scss @@ -36,7 +36,8 @@ } } - textarea { + textarea, + input { background: transparent; border: 0; min-height: 1em; diff --git a/app/controllers/label_templates_controller.rb b/app/controllers/label_templates_controller.rb index 94d92fe78..04d74f29e 100644 --- a/app/controllers/label_templates_controller.rb +++ b/app/controllers/label_templates_controller.rb @@ -5,9 +5,9 @@ class LabelTemplatesController < ApplicationController before_action :check_feature_enabled before_action :check_view_permissions, only: %i(index datatable) - before_action :check_manage_permissions, only: %i(new duplicate set_default delete) + before_action :check_manage_permissions, only: %i(create duplicate set_default delete update) before_action :load_label_templates, only: %i(index datatable) - before_action :load_label_template, only: %i(edit set_default) + before_action :load_label_template, only: %i(show set_default update) layout 'fluid' @@ -25,9 +25,33 @@ class LabelTemplatesController < ApplicationController end end - def new; end + def show + respond_to do |format| + format.json { render json: @label_template, serializer: LabelTemplateSerializer, user: current_user } + format.html + end + end - def edit; end + def create + label_template = LabelTemplate.create!( + team_id: current_team.id, + name: I18n.t('label_templates.new_label_template'), + language_type: :zpl, + format: 'ZPL', + size: '1" x 0.5" / 25.4mm x 12.7mm', + content: Extends::DEFAULT_LABEL_TEMPLATE[:zpl] + ) + + redirect_to label_template_path(label_template, new_label: true) + end + + def update + if @label_template.update(label_template_params) + render json: @label_template, serializer: LabelTemplateSerializer, user: current_user + else + render json: { error: @label_template.errors.messages }, status: :unprocessable_entity + end + end def duplicate ActiveRecord::Base.transaction do @@ -89,4 +113,8 @@ class LabelTemplatesController < ApplicationController def load_label_template @label_template = LabelTemplate.where(team_id: current_team.id).find(params[:id]) end + + def label_template_params + params.require(:label_template).permit(:name, :description, :content) + end end diff --git a/app/datatables/label_template_datatable.rb b/app/datatables/label_template_datatable.rb index da6f8b8a2..74f869d66 100644 --- a/app/datatables/label_template_datatable.rb +++ b/app/datatables/label_template_datatable.rb @@ -44,7 +44,7 @@ class LabelTemplateDatatable < CustomDatatable '8' => I18n.l(record.created_at, format: :full), 'recordInfoUrl' => '', 'DT_RowAttr': { - 'data-edit-url': edit_label_template_path(record), + 'data-edit-url': label_template_path(record), 'data-set-default-url': set_default_label_template_path(record) }, 'manage_permission' => @manage_template diff --git a/app/javascript/packs/vue/label_template.js b/app/javascript/packs/vue/label_template.js new file mode 100644 index 000000000..32f733afb --- /dev/null +++ b/app/javascript/packs/vue/label_template.js @@ -0,0 +1,25 @@ +import TurbolinksAdapter from 'vue-turbolinks'; +import Vue from 'vue/dist/vue.esm'; +import LabelTemplateContainer from '../../vue/label_template/container.vue'; + +Vue.use(TurbolinksAdapter); +Vue.prototype.i18n = window.I18n; + +window.initLabelTemplateComponent = () => { + + new Vue({ + el: '#labelTemplateContainer', + components: { + 'label-template-container': LabelTemplateContainer + }, + data() { + return { + labelTemplateUrl: $('#labelTemplateContainer').data('label-template-url'), + labelTemplatesUrl: $('#labelTemplateContainer').data('label-templates-url'), + newLabel: $('#labelTemplateContainer').data('new-label') + }; + } + }); +}; + +initLabelTemplateComponent(); diff --git a/app/javascript/vue/label_template/container.vue b/app/javascript/vue/label_template/container.vue new file mode 100644 index 000000000..15cb2f6ac --- /dev/null +++ b/app/javascript/vue/label_template/container.vue @@ -0,0 +1,152 @@ + + + diff --git a/app/models/label_template.rb b/app/models/label_template.rb index a4a91d32b..e2b140c29 100644 --- a/app/models/label_template.rb +++ b/app/models/label_template.rb @@ -21,6 +21,13 @@ class LabelTemplate < ApplicationRecord end end + def icon_url + case language_type + when 'zpl' + '/images/label_template_icons/zpl.svg' + end + end + private def default_template diff --git a/app/serializers/label_template_serializer.rb b/app/serializers/label_template_serializer.rb new file mode 100644 index 000000000..6b4ee7b27 --- /dev/null +++ b/app/serializers/label_template_serializer.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class LabelTemplateSerializer < ActiveModel::Serializer + include Rails.application.routes.url_helpers + + attributes :name, :description, :language_type, :icon_url, :urls, :content + + def urls + { + update: label_template_path(object) + } + end +end diff --git a/app/views/label_templates/_index_toolbar.html.erb b/app/views/label_templates/_index_toolbar.html.erb index 8a5a5b39f..00ac0e79a 100644 --- a/app/views/label_templates/_index_toolbar.html.erb +++ b/app/views/label_templates/_index_toolbar.html.erb @@ -1,14 +1,10 @@