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 ? '