From d608f73772a9181911cccbf0e518371a6a257b9d Mon Sep 17 00:00:00 2001 From: alexey Date: Sat, 22 Feb 2025 23:28:36 +0300 Subject: [PATCH] Receipt create. Part 2 --- app.rb | 122 ++++++++++++++++++++--- classes/db.rb | 66 ++++++++++++- classes/gitinfo.rb | 4 +- classes/utilities.rb | 15 +++ db/migrations/202502150000000_create.rb | 2 +- public/js/jquery.dropdown.min.css | 1 + public/js/jquery.dropdown.min.js | 1 + views/header.erb | 5 + views/rcpcrt.erb | 26 ++++- views/rcpedit.erb | 125 ++++++++++++++++++++++++ views/receips.erb | 13 ++- 11 files changed, 356 insertions(+), 24 deletions(-) create mode 100644 classes/utilities.rb create mode 100755 public/js/jquery.dropdown.min.css create mode 100755 public/js/jquery.dropdown.min.js create mode 100644 views/rcpedit.erb diff --git a/app.rb b/app.rb index 1e568eb..800a228 100644 --- a/app.rb +++ b/app.rb @@ -14,6 +14,7 @@ require_relative "classes/config" require_relative "classes/gitinfo" require_relative "classes/db" require_relative "classes/systeminfo" +require_relative "classes/utilities" def print_error_page(error_status, error_meaasge) @page_name = "Ошибка выполнения" @@ -22,14 +23,6 @@ def print_error_page(error_status, error_meaasge) halt erb(:page5xx) end -def sanitize_filename(filename) - filename = filename.strip - sanitized = filename.gsub(/[^a-zA-Z0-9_]/, "_") - sanitized.gsub!(/_+/, "_") - sanitized.gsub!(/^_+|_+$/, "") - sanitized -end - cfg = IniConfig.new() db = DBase.new() @@ -155,11 +148,118 @@ get "/recips" do erb :receips end +get "/recips/:rcp_id" do + repo = GitRepo.new(cfg.get_repo, db) + if repo.path.nil? + print_error_page(503, "Путь к репозиториям не существует") + else + @repo_data = repo.getrepos + @rcp_id = params["rcp_id"] + info = db.get_rcp_info_by_id(@rcp_id) + @page_name = info[:filepath] + @rcp_name = info[:filepath] + if session[:rcp_old_description].nil? + @old_filepath = info[:filepath] + else + @old_filepath = session[:rcp_old_filepath] + end + if session[:rcp_old_description].nil? + @old_description = info[:descr] + else + @old_description = session[:rcp_old_description] + end + if session[:rcp_old_codedata].nil? + @old_codedata = info[:content] + else + @old_codedata = session[:rcp_old_codedata] + end + if session[:rcp_old_gitlst].nil? + @old_gitlst = info[:repos_list] + else + @old_gitlst = session[:rcp_old_gitlst] + end + @error_data = session[:rcpcreate_error] + session[:rcpcreate_error] = nil + session[:rcp_old_filepath] = nil + session[:rcp_old_description] = nil + session[:rcp_old_codedata] = nil + session[:rcp_old_gitlst] = nil + erb :rcpedit + end +end + +post "/recips/:rcp_id" do + rcp_id = params["rcp_id"] + session[:rcp_old_filepath] = params["filepath"] + session[:rcp_old_description] = params["description"] + session[:rcp_old_codedata] = params["codedata"] + session[:rcp_old_gitlst] = params["gitlst"] + if params["filepath"].nil? || params["description"].nil? || params["filepath"].strip == "" || params["description"].strip == "" + session[:rcpcreate_error] = "Имя рецепта и описание не должны быть пустыми" + redirect url("/recips/#{rcp_id}") + else + @error_data = db.updaterecip(rcp_id, params["filepath"], params["description"], params["codedata"], params["gitlst"]) + unless @error_data.nil? + session[:rcpcreate_error] = @error_data + redirect url("/recips/#{rcp_id}") + else + redirect "/recips" + end + end +end + +post "/rcpdelete/:rcp_id" do + input_name = params["rcpnamedup"] + rcp_id = params["rcp_id"] + info = db.get_rcp_info_by_id(rcp_id) + if info.nil? + print_error_page(404, "Рецепта не существует") + else + if info[:filepath] == input_name + db.delete_rcp(rcp_id) + end + redirect "/recips" + end +end + +post "/rcpdelete" do + redirect "/recips" +end + get "/rcpcreate" do @page_name = "Создать новый рецепт" - @error_data = session[:rcpcreate_error] - session[:gitcreate_error] = nil - erb :rcpcrt + @old_filepath = session[:rcp_old_filepath] + @old_description = session[:rcp_old_description] + @old_codedata = session[:rcp_old_codedata] + @old_gitlst = session[:rcp_old_gitlst] + repo = GitRepo.new(cfg.get_repo, db) + if repo.path.nil? + print_error_page(503, "Путь к репозиториям не существует") + else + @repo_data = repo.getrepos + @error_data = session[:rcpcreate_error] + session[:rcpcreate_error] = nil + erb :rcpcrt + end +end + +post "/rcpcreate" do + session[:rcp_old_filepath] = params["filepath"] + session[:rcp_old_description] = params["description"] + session[:rcp_old_codedata] = params["codedata"] + session[:rcp_old_gitlst] = params["gitlst"] + if params["filepath"].nil? || params["description"].nil? || params["filepath"].strip == "" || params["description"].strip == "" + session[:rcpcreate_error] = "Имя рецепта и описание не должны быть пустыми" + redirect "/rcpcreate" + else + @error_data = db.createrecip(params["filepath"], params["description"], params["codedata"], params["gitlst"]) + unless @error_data.nil? + session[:rcpcreate_error] = @error_data + redirect "/rcpcreate" + else + redirect "/recips" + end + end end not_found do diff --git a/classes/db.rb b/classes/db.rb index c57ac48..77188d9 100644 --- a/classes/db.rb +++ b/classes/db.rb @@ -17,8 +17,8 @@ class DBase def creategit(project_name, description) @error = nil - data = Repos.where(reponame: project_name) - unless data.nil? + data = Repos.where(reponame: project_name).first + if data.nil? id = Repos.insert(reponame: project_name, descr: description, public: 1) @last_id = id else @@ -46,4 +46,66 @@ class DBase Repos.where(id: id).delete end end + + def createrecip(filepath, description, codedata, gitlist) + error_data = nil + filepath_san = sanitize_rcptname(filepath) + is_data = Recips.where(filepath: filepath_san).first + if codedata.nil? || codedata.strip == "" + error_data + else + if is_data.nil? + id = Recips.insert(filepath: filepath_san, descr: description, content: codedata) + @last_id = id + if !gitlist.nil? && gitlist.length > 0 + gitlist.each do |item| + data = Repos.where(id: item.to_i).first + unless data.nil? + RepocRecips.insert(repo_id: data[:id], recip_id: id) + end + end + end + error_data + else + "Рецепт с таким именем #{filepath_san} уже существует" + end + end + end + + def updaterecip(id, filepath, description, codedata, gitlist) + error_data = nil + filepath_san = sanitize_rcptname(filepath) + is_data = Recips.where(filepath: filepath_san).first + if codedata.nil? || codedata.strip == "" + error_data + else + unless is_data.nil? + Recips.where(id: id.to_i).update(filepath: filepath_san, descr: description, content: codedata) + RepocRecips.where(recip_id: id.to_i).delete + if !gitlist.nil? && gitlist.length > 0 + gitlist.each do |item| + data = Repos.where(id: item.to_i).first + unless data.nil? + RepocRecips.insert(repo_id: data[:id], recip_id: id) + end + end + end + error_data + else + "Рецепт с таким именем #{filepath_san} не существует" + end + end + end + + def get_rcp_info_by_id(rcpi_id) + info = Recips[rcpi_id.to_i] + gits = RepocRecips.where(recip_id: info[:id]) + info[:repos_list] = gits.map { |item| item[:repo_id].to_s } + info + end + + def delete_rcp(id) + RepocRecips.where(recip_id: id.to_i).delete + Recips.where(id: id.to_i).delete + end end diff --git a/classes/gitinfo.rb b/classes/gitinfo.rb index 91f0f86..0faff98 100644 --- a/classes/gitinfo.rb +++ b/classes/gitinfo.rb @@ -67,13 +67,13 @@ class GitRepo db_info = @db.get_repo_info_by_name(repo_name) unless db_info.nil? db_info = db_info.first - repos_data << { :reponame => db_info.reponame, :descr => db_info.descr, :public => db_info.public } + repos_data << { :reponame => db_info.reponame, :descr => db_info.descr, :public => db_info.public, :id => db_info.id } else result = create_git_db_only(repo_name) if result.nil? db_info = @db.get_repo_info_by_name(repo_name) db_info = db_info.first - repos_data << { :reponame => db_info.reponame, :descr => db_info.descr, :public => db_info.public } + repos_data << { :reponame => db_info.reponame, :descr => db_info.descr, :public => db_info.public, :id => db_info.id } end end end diff --git a/classes/utilities.rb b/classes/utilities.rb new file mode 100644 index 0000000..ca4b704 --- /dev/null +++ b/classes/utilities.rb @@ -0,0 +1,15 @@ +def sanitize_filename(filename) + filename = filename.strip + sanitized = filename.gsub(/[^a-zA-Z0-9_]/, "_") + sanitized.gsub!(/_+/, "_") + sanitized.gsub!(/^_+|_+$/, "") + sanitized +end + +def sanitize_rcptname(filename) + filename = filename.strip + sanitized = filename.gsub(/[^a-zA-Z0-9_\.]/, "_") + sanitized.gsub!(/_+/, "_") + sanitized.gsub!(/^_+|_+$/, "") + sanitized +end diff --git a/db/migrations/202502150000000_create.rb b/db/migrations/202502150000000_create.rb index 1be9a62..dce80c3 100644 --- a/db/migrations/202502150000000_create.rb +++ b/db/migrations/202502150000000_create.rb @@ -27,7 +27,7 @@ Sequel.migration do primary_key :id String :content, text: true String :filepath, text: true - String :desct, text: true + String :descr, text: true Datetime :create_at, default: Sequel.lit("CURRENT_TIMESTAMP") end diff --git a/public/js/jquery.dropdown.min.css b/public/js/jquery.dropdown.min.css new file mode 100755 index 0000000..b3e2cfe --- /dev/null +++ b/public/js/jquery.dropdown.min.css @@ -0,0 +1 @@ +@-webkit-keyframes iui-fadeIn{0%{opacity:0}100%{opacity:1}}@-moz-keyframes iui-fadeIn{0%{opacity:0}100%{opacity:1}}@-ms-keyframes iui-fadeIn{0%{opacity:0}100%{opacity:1}}@-o-keyframes iui-fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes iui-fadeIn{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes iui-fadeOut{0%{opacity:1}100%{opacity:0}}@-moz-keyframes iui-fadeOut{0%{opacity:1}100%{opacity:0}}@-ms-keyframes iui-fadeOut{0%{opacity:1}100%{opacity:0}}@-o-keyframes iui-fadeOut{0%{opacity:1}100%{opacity:0}}@keyframes iui-fadeOut{0%{opacity:1}100%{opacity:0}}.dropdown-multiple,.dropdown-multiple-label,.dropdown-single{position:relative}.dropdown-multiple-label.active .dropdown-main,.dropdown-multiple.active .dropdown-main,.dropdown-single.active .dropdown-main{display:block;-webkit-animation:iui-fadeIn .2s ease-in forwards;-moz-animation:iui-fadeIn .2s ease-in forwards;-ms-animation:iui-fadeIn .2s ease-in forwards;-o-animation:iui-fadeIn .2s ease-in forwards;animation:iui-fadeIn .2s ease-in forwards}.dropdown-multiple-label.active .dropdown-display-label:after,.dropdown-multiple-label.active .dropdown-display:after,.dropdown-multiple.active .dropdown-display-label:after,.dropdown-multiple.active .dropdown-display:after,.dropdown-single.active .dropdown-display-label:after,.dropdown-single.active .dropdown-display:after{border-top:none;border-bottom:10px solid #999;border-left:5px solid transparent;border-right:5px solid transparent}.dropdown-multiple-label.active .dropdown-display,.dropdown-multiple-label.active .dropdown-display-label,.dropdown-multiple.active .dropdown-display,.dropdown-multiple.active .dropdown-display-label,.dropdown-single.active .dropdown-display,.dropdown-single.active .dropdown-display-label{border-bottom-left-radius:0;border-bottom-right-radius:0}.dropdown-display,.dropdown-display-label{position:relative;display:block;margin-bottom:0;font-size:14px;line-height:1.42857143;vertical-align:middle;touch-action:manipulation;cursor:pointer;user-select:none;background-image:none;border:1px solid #ccc;border-radius:4px;color:#333;background-color:#fff}.dropdown-display-label:after,.dropdown-display:after{content:'';position:absolute;border-top:10px solid #999;border-left:5px solid transparent;border-right:5px solid transparent;top:12px;right:8px}.dropdown-clear-all{background-color:#fff;border:none;font-size:22px;z-index:999;color:#999;position:absolute;right:2px;top:2px;display:none;width:25px;height:30px;text-align:center;line-height:30px}.dropdown-clear-all:focus{outline:0}.dropdown-clear-all:hover{color:#ccc;text-decoration:none}.dropdown-display{white-space:nowrap;padding:6px 20px 6px 12px}.dropdown-multiple:hover .dropdown-clear-all,.dropdown-single:hover .dropdown-clear-all{display:block}.dropdown-display .dropdown-chose-list{display:inline-block;vertical-align:middle;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dropdown-display .dropdown-chose-list span:before{content:','}.dropdown-display .dropdown-chose-list span:first-child:before{content:''}.dropdown-display .placeholder{display:none}.dropdown-display .placeholder:first-child{position:absolute;height:100%;width:100%;top:0;left:0;color:#999;display:block;text-indent:10px;font-size:13px;line-height:32px}.dropdown-display input{border:0;outline:0}.dropdown-display-label{cursor:text;padding:6px 25px 5px 0}.dropdown-display-label .dropdown-search{display:inline-block}.dropdown-display-label input,.dropdown-display-label input:focus{border:none;outline:0}.dropdown-display-label .dropdown-chose-list{display:inline-block;padding:0 5px}.dropdown-display-label .dropdown-chose-list .placeholder{display:none}.dropdown-display-label .dropdown-selected{position:relative;margin:0 5px 5px 0;padding:0 20px 0 5px;border:1px solid #aaa;max-width:100%;border-radius:3px;background-repeat:repeat-x;color:#333;cursor:default;display:inline-block}.dropdown-display-label .dropdown-selected .del{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0;float:right;line-height:1;color:#999;position:absolute;right:3px;top:0}.dropdown-display-label .dropdown-selected .del:after{content:'\D7';font-size:16px}.dropdown-main{position:absolute;top:100%;left:0;z-index:1010;width:100%;color:#444;box-sizing:border-box;background-color:#fff;border:1px solid #ccc;border-radius:0 0 4px 4px;box-shadow:0 6px 12px rgba(0,0,0,.175);margin-top:-1px;border-top:0;padding:4px 7px;display:none}.dropdown-main ul{overflow-x:hidden;overflow-y:auto;max-height:240px;margin:0;padding:0}.dropdown-main input{margin-top:0;display:block;box-sizing:border-box;height:30px;border:1px solid #ccc;width:100%;text-indent:5px;border-radius:3px}.dropdown-main .dropdown-search{display:block;padding:5px 0}.dropdown-group{font-weight:700}.dropdown-group,.dropdown-option{margin:0;padding-left:12px;list-style:none;line-height:26px;word-wrap:break-word}.dropdown-option{cursor:pointer}.dropdown-option:focus,.dropdown-option:hover{background-color:#efefef;outline:0}.dropdown-option[disabled]{color:#ddd;background-color:#fff;cursor:not-allowed;text-decoration:line-through}.dropdown-option.dropdown-chose:after{content:'';float:right;width:10px;height:10px;background:#4AB1E9;border-radius:100%;margin:8px 5px 0 0}.dropdown-maxItem-alert,.dropdown-minItem-alert{position:absolute;top:0;left:0;background-color:#e4e3e2;width:100%;height:39px;line-height:39px;padding:0 5px;border-radius:5px;color:#999;-webkit-animation:iui-fadeIn .2s ease-in forwards;-moz-animation:iui-fadeIn .2s ease-in forwards;-ms-animation:iui-fadeIn .2s ease-in forwards;-o-animation:iui-fadeIn .2s ease-in forwards;animation:iui-fadeIn .2s ease-in forwards} diff --git a/public/js/jquery.dropdown.min.js b/public/js/jquery.dropdown.min.js new file mode 100755 index 0000000..81b256c --- /dev/null +++ b/public/js/jquery.dropdown.min.js @@ -0,0 +1 @@ +(function (e) { "use strict"; function o() { } function n(e, o, n) { var t, i, l, a = null, d = 0; n || (n = {}); var s = function () { d = n.leading === !1 ? 0 : (new Date).getTime(), a = null, l = e.apply(t, i), a || (t = i = null) }; return function () { var r = (new Date).getTime(); d || n.leading !== !1 || (d = r); var c = o - (r - d); return t = this, i = arguments, c <= 0 || c > o ? (clearTimeout(a), a = null, d = r, l = e.apply(t, i), a || (t = i = null)) : a || n.trailing === !1 || (a = setTimeout(s, c)), l } } function t() { var e = this.isLabelMode, o = this.config.searchable, n = o ? '' + this.config.input + "" : ""; return e ? '' : '×" } function i() { var o = this, n = o.config, t = o.$el, i = t.find(".dropdown-minItem-alert"), l = n.minCountErrorMessage; clearTimeout(o.itemCountAlertTimer), 0 === i.length && (l || (l = "Минимальный выбор" + n.minCount + "个"), i = e('")), t.append(i), o.itemCountAlertTimer = setTimeout(function () { t.find(".dropdown-minItem-alert").remove() }, f) } function l() { var o = this, n = o.config, t = o.$el, i = t.find(".dropdown-maxItem-alert"), l = n.limitCountErrorMessage; clearTimeout(o.itemLimitAlertTimer), 0 === i.length && (l || (l = "На выбор" + n.limitCount + "个"), i = e('")), t.append(i), o.itemLimitAlertTimer = setTimeout(function () { t.find(".dropdown-maxItem-alert").remove() }, f) } function a(o) { var n = o || ""; return n = n.replace(/]*>/gi, "").replace("", ""), n = n.replace(/<\/optgroup>/gi, ""), n = n.replace(/]*>/gi, function (e) { var o = /label="(.[^"]*)"(\s|>)/.exec(e), n = /data\-group\-id="(.[^"]*)"(\s|>)/.exec(e); return '" }), n = n.replace(//gi, function (o) { var n = e(o).val(), t = />(.*)<\//.exec(o), i = o.indexOf("selected") > -1, l = o.indexOf("disabled") > -1, a = ""; o.replace(/data-(\w+)="?(.[^"]+)"?/g, function (e) { a += e + " " }); return "" }) } function d(o) { var n = this, t = {}, i = "", l = [], a = 0, d = n.config.extendProps; return !(!o || !o.length) && (e.each(o, function (o, n) { var i = n.groupId, s = n.disabled ? " disabled" : "", r = n.selected && !s ? " selected" : "", c = ""; e.each(d, function (e, o) { n[o] && (c += "data-" + o + '="' + n[o] + '" ') }); var p = "" + n.name + ""; r && (l.push('' + n.name + ''), a++), i ? t[n.groupId] ? t[n.groupId] += p : t[n.groupId] = n.groupName + "&janking&" + p : t[o] = p }), e.each(t, function (e, o) { var n = o.split("&janking&"); if (2 === n.length) { var t = n[0], l = n[1]; i += '' + l + "" } else i += o }), [i, l, a]) } function s(o) { function n(o, n) { var t = e(n); this.id = t.prop("value"), this.name = t.text(), this.disabled = t.prop("disabled"), this.selected = t.prop("selected") } var t = o, i = []; return e.each(t.children(), function (o, t) { var l = {}, a = {}, d = e(t); "OPTGROUP" === t.nodeName ? (a.groupId = d.data("groupId"), a.groupName = d.attr("label"), e.each(d.children(), e.proxy(n, l)), e.extend(l, a)) : e.each(d, e.proxy(n, l)), i.push(l) }), i } function r(o, n) { this.$el = e(n), this.$select = this.$el.find("select"), this.placeholder = this.$select.attr("placeholder"), this.config = o, this.name = [], this.isSingleSelect = !this.$select.prop("multiple"), this.selectAmount = 0, this.itemLimitAlertTimer = null, this.isLabelMode = "label" === this.config.multipleMode, this.init() } var c = function () { var e = navigator.userAgent.toLowerCase(); if (e.indexOf("safari") !== -1) return !(e.indexOf("chrome") > -1) }(), p = { readonly: !1, minCount: 0, minCountErrorMessage: "", limitCount: 1 / 0, limitCountErrorMessage: "", input: '', data: [], searchable: !0, searchNoData: '
  • Не можете найти никаких данных, попробуйте другое слово /(ㄒoㄒ)/~~
  • ', init: o, choice: o, extendProps: [] }, u = { up: 38, down: 40, enter: 13 }, h = { click: "click.iui-dropdown", focus: "focus.iui-dropdown", keydown: "keydown.iui-dropdown", keyup: "keyup.iui-dropdown" }, f = 1e3, m = { show: function (o) { o.stopPropagation(); var n = this; e(document).trigger("click.dropdown"), n.$el.addClass("active") }, search: n(function (o) { var n = this, t = n.config, i = n.$el, l = e(o.target), s = l.val(), r = n.config.data, c = []; o.keyCode > 36 && o.keyCode < 41 || (e.each(r, function (e, o) { (o.groupName && o.groupName.toLowerCase().indexOf(s.toLowerCase()) > -1 || o.name.toLowerCase().indexOf(s.toLowerCase()) > -1 || "" + o.id == "" + s) && c.push(o) }), i.find("ul").html(a(d.call(n, c)[0]) || t.searchNoData)) }, 300), control: function (o) { var n, t, i, l = o.keyCode, a = u, d = 0; l !== a.down && l !== a.up || (n = l === a.up ? -1 : 1, i = this.$el.find("[tabindex]"), t = i.index(e(document.activeElement)), d = t === -1 ? n + 1 ? -1 : 0 : t, d += n, d === i.length && (d = 0), i.eq(d).focus(), o.preventDefault()) }, multiChoose: function (o, n) { var t, a = this, d = a.config, s = a.$select, r = e(o.target), c = r.attr("data-value"), p = r.hasClass("dropdown-chose"), u = []; if (r.hasClass("dropdown-display")) return !1; if (p) r.removeClass("dropdown-chose"), a.selectAmount--; else { if (!(a.selectAmount < d.limitCount)) return l.call(a), !1; r.addClass("dropdown-chose"), a.selectAmount++ } a.name = [], e.each(d.data, function (e, o) { "" + o.id == "" + c && (t = o, o.selected = !p), o.selected && (u.push(o.name), a.name.push('' + o.name + '')) }), s.find('option[value="' + c + '"]').prop("selected", !p), p && a.selectAmount < d.minCount && i.call(a), a.$choseList.find(".dropdown-selected").remove(), a.$choseList.prepend(a.name.join("")), a.$el.find(".dropdown-display").attr("title", u.join(",")), d.choice.call(a, o, t) }, singleChoose: function (o) { var n = this, t = n.config, i = n.$el, l = n.$select, a = e(o.target), d = a.attr("data-value"), s = a.hasClass("dropdown-chose"); return !a.hasClass("dropdown-chose") && !a.hasClass("dropdown-display") && (n.name = [], i.removeClass("active").find("li").not(a).removeClass("dropdown-chose"), a.toggleClass("dropdown-chose"), e.each(t.data, function (e, o) { o.selected = !1, "" + o.id == "" + d && (o.selected = s ? 0 : 1, o.selected && n.name.push('' + o.name + '')) }), l.find('option[value="' + d + '"]').prop("selected", !0), n.name.push('' + n.placeholder + ""), n.$choseList.html(n.name.join("")), void t.choice.call(n, o)) }, del: function (o) { var n = this, t = n.config, i = e(o.target), l = i.data("id"); return e.each(n.name, function (e, o) { if (o.indexOf('data-id="' + l + '"') !== -1) return n.name.splice(e, 1), !1 }), e.each(n.config.data, function (e, o) { if ("" + o.id == "" + l) return o.selected = !1, !1 }), n.selectAmount--, n.$el.find('[data-value="' + l + '"]').removeClass("dropdown-chose"), n.$el.find('[value="' + l + '"]').prop("selected", !1).removeAttr("selected"), i.closest(".dropdown-selected").remove(), t.choice.call(n, o), !1 }, clearAll: function (o) { var n = this, t = n.config; return o && o.preventDefault(), console.log(this), this.$choseList.find(".del").each(function (o, n) { e(n).trigger("click") }), t.minCount > 0 && i.call(n), this.$el.find(".dropdown-display").removeAttr("title"), !1 } }; r.prototype = { init: function () { var e = this, o = e.config, n = e.$el; e.$select.hide(), n.addClass(e.isSingleSelect ? "dropdown-single" : e.isLabelMode ? "dropdown-multiple-label" : "dropdown-multiple"), 0 === o.data.length && (o.data = s(e.$select)); var t = d.call(e, o.data); e.name = t[1], e.selectAmount = t[2], e.$select.html(t[0]), e.renderSelect(), e.changeStatus(o.disabled ? "disabled" : !!o.readonly && "readonly"), e.config.init() }, renderSelect: function (o, n) { var i, l = this, d = l.$el, s = l.$select, r = a(s.prop("outerHTML")); o ? d.find("ul")[n ? "html" : "append"](r) : (i = t.call(l).replace("{{ul}}", "
      " + r + "
    "), d.append(i).find("ul").removeAttr("style class")), n && (l.name = [], l.$el.find(".dropdown-selected").remove(), l.$select.val("")), l.$choseList = d.find(".dropdown-chose-list"), l.isLabelMode || l.$choseList.html(e('').text(l.placeholder)), l.$choseList.prepend(l.name ? l.name.join("") : []) }, bindEvent: function () { var o = this, n = o.$el, t = c ? h.click : h.focus; n.on(h.click, function (e) { e.stopPropagation() }), n.on(h.click, ".del", e.proxy(m.del, o)), o.isLabelMode ? (n.on(h.click, ".dropdown-display-label", function () { n.find("input").focus() }), o.config.searchable ? n.on(h.focus, "input", e.proxy(m.show, o)) : n.on(h.click, e.proxy(m.show, o)), n.on(h.keydown, "input", function (e) { 8 === e.keyCode && "" === this.value && o.name.length && n.find(".del").eq(-1).trigger("click") })) : (n.on(t, ".dropdown-display", e.proxy(m.show, o)), n.on(t, ".dropdown-clear-all", e.proxy(m.clearAll, o))), n.on(h.keyup, "input", e.proxy(m.search, o)), n.on(h.keyup, function (n) { var t = n.keyCode, i = u; t === i.enter && e.proxy(o.isSingleSelect ? m.singleChoose : m.multiChoose, o, n)() }), n.on(h.keydown, e.proxy(m.control, o)), n.on(h.click, "li[tabindex]", e.proxy(o.isSingleSelect ? m.singleChoose : m.multiChoose, o)) }, unbindEvent: function () { var e = this, o = e.$el, n = c ? h.click : h.focus; o.off(h.click), o.off(h.click, ".del"), e.isLabelMode ? (o.off(h.click, ".dropdown-display-label"), o.off(h.focus, "input"), o.off(h.keydown, "input")) : (o.off(n, ".dropdown-display"), o.off(n, ".dropdown-clear-all")), o.off(h.keyup, "input"), o.off(h.keyup), o.off(h.keydown), o.off(h.click, "[tabindex]") }, changeStatus: function (e) { var o = this; "readonly" === e ? o.unbindEvent() : "disabled" === e ? (o.$select.prop("disabled", !0), o.unbindEvent()) : (o.$select.prop("disabled", !1), o.bindEvent()) }, update: function (e, o) { var n = this, t = n.config, i = (n.$el, o || !1); if ("[object Array]" === Object.prototype.toString.call(e)) { t.data = i ? e.slice(0) : t.data.concat(e); var l = d.call(n, t.data); n.name = l[1], n.selectAmount = l[2], n.$select.html(l[0]), n.renderSelect(!0, i) } }, destroy: function () { this.unbindEvent(), this.$el.children().not("select").remove(), this.$el.removeClass("dropdown-single dropdown-multiple-label dropdown-multiple"), this.$select.show() }, choose: function (o, n) { var t = "[object Array]" === Object.prototype.toString.call(o) ? o : [o], i = this, l = void 0 === n || !!n; e.each(t, function (e, o) { var t = i.$el.find('[data-value="' + o + '"]'), a = t.hasClass("dropdown-chose"); a !== l && t.trigger(h.click, n || !0) }) }, reset: function () { m.clearAll.call(this) } }, e(document).on("click.dropdown", function () { e(".dropdown-single,.dropdown-multiple,.dropdown-multiple-label").removeClass("active") }), e.fn.dropdown = function (o) { return this.each(function (n, t) { e(t).data("dropdown", new r(e.extend(!0, {}, p, o), t)) }), this } })(jQuery); \ No newline at end of file diff --git a/views/header.erb b/views/header.erb index edf08b8..87e89f5 100644 --- a/views/header.erb +++ b/views/header.erb @@ -7,6 +7,7 @@ <%= @page_name %> + @@ -20,6 +21,10 @@
    + + главная + + | git-репозитории diff --git a/views/rcpcrt.erb b/views/rcpcrt.erb index 4240a5d..4e16e47 100644 --- a/views/rcpcrt.erb +++ b/views/rcpcrt.erb @@ -9,6 +9,7 @@ toolbar: "search, go_to_line, fullscreen, |, undo, redo, |, select_font,|, highlight, reset_highlight, word_wrap, |, syntax_selection" }); + <% unless @error_data.nil? %>
    @@ -18,19 +19,38 @@
    - +
    - +
    - + +
    +
    + +
    + +
    + <%= erb :footer %> \ No newline at end of file diff --git a/views/rcpedit.erb b/views/rcpedit.erb new file mode 100644 index 0000000..7a2e480 --- /dev/null +++ b/views/rcpedit.erb @@ -0,0 +1,125 @@ +<%= erb :header %> + + + + <% unless @error_data.nil? %> +
    + +
    + <% end %> +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    + +
    +
    +
    + + +
    +
    +
    +
    + + + +<%= erb :footer %> \ No newline at end of file diff --git a/views/receips.erb b/views/receips.erb index c2d7b0f..a0b0c00 100644 --- a/views/receips.erb +++ b/views/receips.erb @@ -1,16 +1,19 @@ <%= erb :header %>
    -
    +

    Доступные рецепты

    Страница управления рецептами

    +
    <% @rcp_data.each do |item| %>