puzzle/views/admin/objects/group_object.ejs
n0rdye 1a8831d6ad modified: object.js
modified:   public/lib/fn.js
	modified:   public/lib/inter.js
	modified:   public/lib/inter_group_object.js
	modified:   public/lib/inter_temp.js
	modified:   views/admin/objects/group_object.ejs
	modified:   views/admin/objects/object_creation.ejs
	modified:   views/admin/objects/object_edit.ejs
	modified:   views/project.ejs
2023-11-16 17:32:11 +00:00

615 lines
23 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<%- include('../../static/start.ejs',{name:"",async:true}) %>
<%- include('../../header.ejs') %>
<script src="/lib/interact.js"></script>
<script src="/lib/html2canvas.js"></script>
<style>
.drag{
height: 5vw;
width: 5vw;
position: absolute;
text-align: center;
margin: auto;
z-index: 10;
touch-action: none;
}
#drags{
position: absolute;
margin: auto;
}
.spawn{
object-fit: contain;
}
.zones{
margin-block: 10px;
}
.wall {
/* border: dashed 4px transparent; */
border-radius: 4px;
transition: background-color 0.3s;
position: absolute;
inset: 0px;
margin: 5px auto;
width: 400px;
height: 200px;
background-color: #fff;
/* background-image: url("/img/bg1red.png"); */
background-size: 200px;
background-repeat: repeat;
background-position: bottom 0px left 0px;
border: 2px solid black;
/* overflow: visible; */
z-index: -1;
}
.createzone {
background-color: #bfe4ff;
border: dashed 4px transparent;
border-radius: 0.4vw;
height: 3vw;
width: 3vw;
margin: 10px;
margin-top: 0px;
padding: 0.8vw;
transition: background-color 0.3s;
}
.trash {
background-color: #bfe4ff;
border: dashed 4px transparent;
border-radius: 4px;
/* margin: 10px auto 30px; */
/* padding: 10px; */
height: 50px;
width: 50px;
transition: background-color 0.3s;
text-align: center;
/* z-index: -1; */
}
.czones{
display: flex;
margin: 0px auto;
margin-top: 3vh;
/* justify-content: space-around; */
flex-wrap: wrap;
width: 75%;
height: 40vh;
/* overflow-x: auto; */
}
.drop-active {
border-color: #aaa;
}
/* .drop-target {
background-color: #29e;
border-color: #fff;
border-style: solid;
} */
#proj_top{
margin: auto;
width: 90%;
display: flex;
justify-content: space-around;
}
#proj_name{
background-color: #aaa;
border: 0px;
text-align: center;
}
.inputs{
display: flex;
width: 80vw;
margin: auto;
padding-block: 20px;
padding-bottom: 0px;
/* margin-top: 50px; */
}
#group{
display: none;
position: absolute;
padding: 0px;
margin: 0px;
}
</style>
<div id="project_menu" class="cmenu">
<button id='proj_csave_btn' onclick='save_proj()'>сохранить в облако</button> <br>
<!-- <button id='proj_cload_btn' onclick='load_proj_cloud()'>загрузить из облака</button> <br> -->
<!-- <button id='proj_lsave_btn' onclick='save_proj_local()'>сохранить на локальное хранилище</button> <br>
<button id='proj_lload_btn' onclick='load_proj_local()'>загрузить из локальное хранилище</button> <br> -->
<!-- <button id='proj_del_btn' onclick='del_proj()'>удалить проект</button> <br> -->
</div>
<!-- <div class="dropzone"></div> -->
<div class="inputs">
<div id="wall_input" style="display: flex;justify-content: space-between;width: 95%;margin-left: 20px;">
<div style="display: flex;width: 16vw;justify-content: space-between;">
<label for="wall_height" style="margin: auto;">Высота стены</label>
<input type="text" id="wall_height" style="width: 5vw; text-align: center; border-radius: 0.5vw; border: 1px solid gray;" value="2" oninput="this.value = this.value.replace(/[^0-9.]/g, '0').replace(/(\..*?)\..*/g, '$1').replace(/^0[^.]/, '0');wall_size_change('height');resize_drags();">
<label for="wall_width" style="margin: auto;">М.</label>
</div>
<div style="display: flex;width: 16vw;justify-content: space-between;">
<label for="wall_width" style="margin: auto;">Длина стены</label>
<input type="text" id="wall_width" style="width: 5vw; text-align: center; border-radius: 0.5vw; border: 1px solid gray;" value="4" oninput="this.value = this.value.replace(/[^0-9.]/g, '0').replace(/(\..*?)\..*/g, '$1').replace(/^0[^.]/, '0');wall_size_change('width');resize_drags();">
<label for="wall_width" style="margin: auto;">М.</label>
</div>
<div style="display: flex;width: 16vw;justify-content: space-between;">
<label for="wall_color" style="margin: auto;">Цвет стены</label>
<input type="color" id="wall_color" style="width: 5vw; border-radius: 0.5vw; border: 1px solid gray; min-height: 3.9vw;" value="#FFFFFF" onchange="wall_color_change()">
</div>
<div id="cost_div" style="display: flex;width: 15vw;justify-content: space-between;">
<button id="proj_cost" class="menu_btn" style="width: 100%;z-index: 3;">
<div id="proj_cost_text" style="pointer-events: none;">Расчет стоимости</div>
<img src="/img/drop.png" style="width: 1vw;height: 0.5vw;pointer-events: none;" alt="\/">
</button>
<style>
#cost_list li{
display: flex;
justify-content: space-between;
width: 14vw;
padding-block: 0.4vw;
}
#cost_list{
list-style-type: none;
padding-left: 0px;
margin-top: 59px;
position: absolute;
width: 14vw;
padding: 0.45vw;
}
</style>
<ul id="cost_list" class="cmenu">
</ul>
<!-- <div style="display: flex;"><div id="proj_cost"></div>&nbsp;руб.</div> -->
</div>
<!-- <div style="display: flex;width: 150px;justify-content: space-between;">
<label style="margin: auto;">Расчёт стоимости</label>
</div> -->
</div>
<!-- <img class="trash" style="height: 100px; width: 100px;" src="/img/shadow-energy.gif" alt="чёрная дыра"> -->
</div>
<div class="zones" style="position: relative;">
<div id="drags">
</div>
<div class="wall dropzone" id="wall"></div>
</div>
<div style="display:flex; justify-content: space-around;"></div>
<div class="inputs" style="display: flex;justify-content: space-between;height: 5vh;">
<div id="obj_color_div" style="justify-content: space-evenly; width: 50vw;display: none;transform: translateX(30%);">
<label for="obj_colors" style="min-width: 10vw;">цвет объекта</label>
<div id="obj_colors" style="display: flex; width: 30vw;overflow: auto;height: 50px;"></div>
<!-- <input id="obj_color" type="color" onchange="obj_color_change(event)"> -->
</div>
</div>
<div class="inputs" style="display: flex;justify-content: space-between;">
<style>
.btn_icon{
border: 1px solid gray;
border-radius: 0.5vw;
padding: 0.5vw;
height: 2vw;
width: 2vw;
cursor: pointer;
}
.btn_icon img{
height: 2vw;
width: 2vw;
}
</style>
<div style="display: flex;justify-content: space-between; width: 35vw;">
<div class="btn_icon"><img src="/img/icon/copy.png" alt="copy"></div>
<div class="btn_icon" onclick="go_back()"><img src="/img/icon/back.png" alt="back"></div>
<div class="btn_icon" onclick="go_forw()"><img src="/img/icon/forw.png" alt="forw"></div>
<div class="btn_icon" onclick="obj_del()"><img src="/img/icon/del.png" alt="del"></div>
<div class="layer_changer">
<div class="btn_icon layer_btn" onclick="obj_change_layer('up')"><img src="/img/icon/up.png" alt="up"></div>
<input id="layer_inp" type="number" oninput="obj_change_layer('inp')">
<div class="btn_icon layer_btn" onclick="obj_change_layer('down')"><img src="/img/icon/down.png" alt="down"></div>
</div>
<style>
#layer_inp{
width: 2vw;
appearance: textfield;
text-align: center;
border: 0px;
}
.layer_btn{
border: 0px;
}
.layer_changer{
display: flex;
background-color: white;
border: 1px gray solid;
border-radius: 0.5vw;
}
</style>
</div>
<div style="display: flex;justify-content: space-between; width: 15vw;">
<div><input type="checkbox" id="trans_checkbox" checked="true" onchange='wall_color_change()'><label for="trans_checkbox">прозрачный фон</label></div>
</div>
<div style="display: flex;justify-content: space-between; width: 7vw;">
<div id="save_btn_icon" class="btn_icon" onclick="save()"><img src="/img/icon/save.png" alt="save"></div>
<!-- <div class="btn_icon" onclick="document.getElementById('import_file').click();"><img src="/img/icon/download.png" alt="load"></div> -->
<!-- <input type='file' id="import_file" style="display: none;" accept="application/JSON" onchange='openFile(event,load_file)'> -->
</div>
</div>
<div class="inputs" style="display: flex;justify-content: space-between;margin-top: 0px;">
<div id="obj_group" style="display: flex;justify-content:space-evenly; width: 100vw;">
<!-- <button name="" id="group_drop" >Помехи на стене</button> -->
<style>
.obj_group{
/* width: 100%; */
display: flex;
padding-block: 0.3vw;
}
.obj_group label{
width: 90%;
/* padding-inline: 0.3vw; */
}
.group_drop{
width: 15vw;
padding: 2px;
min-width: 15vw;
}
.group_drop *{
pointer-events: none;
overflow: auto;
}
.group_drop img{
width: 1vw;
height: 0.5vw;
}
</style>
<div id="obj_parts" style="min-width: 50vw;display: flex;justify-content: space-evenly;">
</div>
<style>
.group_inp{
height: 1vw;
width: 1vw;
border: 0px;
border-radius: 0.4vw;
overflow: auto;
}
</style>
<ul id="group" class="cmenu"></ul>
</div>
</div>
<div class="czones"></div>
<script src="/lib/inter_group_object.js"></script>
<script>
const get_object_id = new URL(window.location).searchParams.get("object_id");
const get_object_name = new URL(window.location).searchParams.get("object_name");
document.getElementById("layer_inp").value = 0;
img_cache(()=>{})
wall_size_change('height');resize_drags();
wall_size_change('width');resize_drags();
function img_download(){
let wait_msg = msg("делаем фото",{type:"wait"})
proj_img((src)=>{
msg("изображение проекта готово",{time:3})
downloadImg(src,`${proj_name}.png`)
},false)
}
function get_data(name,callback) {
$.post( "/get_obj",{name:name,key:"*"})
.done(function( res ) {
if(res["out"] == "good"){
// Object.entries(res["body"]).forEach(([key,value]) => {
// if(id == value["id"]){
// callback(value)
// }
// });
console.log(res["body"]);
callback(res["body"])
}
});
}
function save() {
let wait_msg = msg("Сохраняем изображение", {type:"wait"})
get_data(get_object_name,(data)=>{
proj_img((src_orig)=>{
removeImageBackground(src_orig).then((src_chaged)=>{
src = (JSON.parse(document.getElementById("trans_checkbox").checked) == true)? src_chaged:src_orig;
console.log("posting");
$.post( "/admin/object/grouped/save",{name:data["name"],data:src,json:JSON.stringify(objs),id:data["id"],cost:objs["total"]})
.done(function( res ) {
msg_del(wait_msg.id)
goto(`/admin/objects?object_id=${data["id"]}`);
});
})
})
})
}
function proj_img(callback,cost = false){
obj_selection(true)
let width = (parseInt(document.getElementById("wall").style.width))
document.getElementById("drags").append(document.getElementById("wall"));
document.getElementById("drags").style.height = document.getElementById("wall").style.height;
document.getElementById("cost_list").style.left = "";
Object.values(document.getElementsByClassName("spawn")).forEach((spawn)=>{
spawn.src = "";
})
if(cost == true){
width += document.getElementById("proj_cost").getBoundingClientRect().width;
document.getElementById("drags").append(document.getElementById("cost_div"));
document.getElementById("cost_div").style.marginLeft = `${parseInt(document.getElementById("wall").style.width) + 4}px`;
document.getElementById("cost_list").style.display = "block";
}
html2canvas(document.getElementById("drags"),{
y:7,
x:2,
width:width,
logging:false
// scale:0.2
}).then(canvas => {
if(cost == true){
document.getElementById("cost_div").style.marginLeft = `0`;
document.getElementById("cost_list").style.display = "none";
document.getElementById("wall_input").append(document.getElementById("cost_div"));
}
document.getElementsByClassName("zones")[0].append(document.getElementById("wall"));
let src = "";
src = canvas.toDataURL();
// console.log(src);
callback(src)
drag_start();
});
}
function obj_colors_load(callback) {
let div = document.getElementById("obj_colors");
div.innerHTML = "";
load_colors((colors)=>{
Object.entries(colors).forEach(([key,value]) => {
// console.log(value);
let color_div = document.createElement("div");
color_div.style = `background-color: #${value["color"]}; border-radius: 50%;height: 2vw;min-width: 2vw;margin-inline: 0.5vw;`;
color_div.classList.add("color_palette");
color_div.id=`color_${value["color"]}`;
color_div.setAttribute("color",`${value["color"]}`)
color_div.setAttribute("onclick",`clear_palette();document.getElementById('color_${value["color"]}').style.border = "1px blue solid";obj_color_change('${value["color"]}')`)
color_div.title = `#${value["color"]}`;
div.append(color_div);
if(key = Object.keys(colors).at(-1)){
if(callback)callback();
}
});
})
}
function wall_color_change(){
if (proj_state == "loaded"){objs_back.push(JSON.parse(JSON.stringify(objs)));}
if (JSON.parse(document.getElementById("trans_checkbox").checked) == true) {
let wall = document.getElementById("wall")
wall.style.backgroundColor = "#ffffff";
objs["color"] = "#ffffff";
document.getElementById("wall_color").disabled = true;
}
else{
document.getElementById("wall_color").disabled = false;
let wall = document.getElementById("wall")
let color = document.getElementById("wall_color")
wall.style.backgroundColor = color.value;
objs["color"] = color.value;
}
}
function obj_color_change(color,in_obj = null){
if(color != "null"){
if (proj_state == "loaded"){objs_back.push(JSON.parse(JSON.stringify(objs)));}
let obj = (in_obj == null)? document.getElementById(cur_obj):in_obj;
// console.log(color);
color_change(color,obj.getAttribute("data-img"),(img)=>{
obj.src = img;
obj.setAttribute("color",color)
objs[obj.classList[0]][obj.id]["color"] = color;
});
}
}
function go_back(){
if(objs_back.length > 0){
objs_forw.push(objs);
objs = objs_back.at(-1);
objs_back.pop();
reload();
calc_total();
}
}
function go_forw(){
if(objs_forw.length > 0){
objs_back.push(objs);
objs = objs_forw.at(-1);
objs_forw.pop();
reload();
calc_total();
}
}
function obj_change_layer(type) {
let obj = document.getElementById(cur_obj);
if(obj != null){
let cur_layer = obj.style.zIndex;
if (type == "up" && cur_layer < 10000){
let new_layer = parseInt(cur_layer) + 1;
objs[obj.classList[0]][obj.getAttribute("id")].layer = new_layer;
obj.style.zIndex = new_layer;
obj.setAttribute("layer",new_layer);
document.getElementById("layer_inp").value = new_layer;
} else if (type == "down" && cur_layer > 0){
let new_layer = parseInt(cur_layer) - 1;
objs[obj.classList[0]][obj.getAttribute("id")].layer = new_layer;
obj.style.zIndex = new_layer;
obj.setAttribute("layer",new_layer);
document.getElementById("layer_inp").value = new_layer;
}
else if ((type == "inp")){
let inp_val = parseInt(document.getElementById("layer_inp").value);
if(inp_val >= 0 && inp_val < 10000){
objs[obj.classList[0]][obj.getAttribute("id")].layer = inp_val;
obj.style.zIndex = inp_val;
}
else{
document.getElementById("layer_inp").value = cur_layer;
}
}
}
// console.log(objs[obj.classList[0]][obj.getAttribute("id")]);
}
function obj_del(){
if (proj_state == "loaded"){objs_back.push(JSON.parse(JSON.stringify(objs)));}
document.getElementById("layer_inp").value = 0;
try{
let drag = document.getElementById(cur_obj);
if(drag.id != "none"){
console.log(cur_obj);
// console.log(drag.classList);
if(objs[drag.classList[0]] != null&&objs[drag.classList[0]][drag.id] != null) {
console.log(objs[drag.classList[0]]);
delete objs[drag.classList[0]][drag.id];
if (Object.keys(objs[drag.classList[0]]).length < 1){
delete objs[drag.classList[0]];
}
}
calc_total()
drag.remove();
document.getElementById("obj_color_div").style.display = "none";
cur_obj = null;
}
}
catch{msg("объект не выбран")}
}
function group_drop(){
let e = document.getElementById("group_drop")
setTimeout(()=>{
document.getElementById("group").style.display = "block";
// document.getElementById("group").style.left = document.getElementById("group_drop").getBoundingClientRect().left;
let childs = document.getElementById("group").getElementsByTagName("input");
let i = 0;
Object.entries(childs).forEach(([key,value]) => {
console.log(key,value);
if(value.checked == true){
get_objs(value)
i++;
}
if (i==0){
// document.getElementsByClassName("czones")[0].innerHTML = "";
drag_start()
// e.removeChild(e.getElementsByClassName(value))
}
});
},1)
}
load_parts((db)=>{
let parts = document.getElementById("obj_parts");
Object.values(db).forEach((value)=>{
let part = document.createElement("button")
let part_text = document.createElement("div")
let part_drop = document.createElement("img")
part_drop.src = "/img/drop.png";
part_drop.alt = "\/";
part_text.innerText = `${value["name"].replaceAll("$", " ")}`;
part.id = `group_drop-${value["id"]}`;
part.classList.add("menu_btn")
part.classList.add("group_drop")
part.setAttribute("groups",`${value["groups"]}`)
part.setAttribute("count",`${value["count"]}`)
part.setAttribute("no-cost",`${value["no-cost"]}`)
part.setAttribute("pid",`${value["id"]}`)
part.append(part_text);
part.append(part_drop);
parts.append(part);
console.log(value);
})
})
function gids_change(){
get_objs();
drag_start()
}
function get_groups(callback){
// let select = document.getElementById("group");
// let name = select.options[select.selectedIndex].text;
load_groups(callback(),gids);
}
// get_groups(()=>{
// get_objs();
// });
function get_objs(group_div){
document.getElementsByClassName("czones")[0].innerHTML = "";
gids.forEach(group => {
load_objs((data)=>{
data.forEach(value => {
let czones = document.getElementsByClassName("czones")[0];
let czone = document.createElement('div');
czone.classList.add(value["name"]);
czone.classList.add("createzone");
czones.append(czone)
});
drag_start()
},group)
});
drag_start()
}
// console.log(proj_name);
// let menu = document.getElementById("project_menu");
// document.getElementById("top_panel_left").innerHTML = `<div id='proj_menu' class="menu_btn">настройки проекта</div>`;
// drag_start();
// console.log(px_ratio);
$(window).resize(function(){isZooming();});
function isZooming(){
resize_drags();
}
if(get_object_id != null){
$.post("/admin/object/grouped/load",{id:get_object_id})
.done(function( res ) {
if(res["out"] == "good"){
console.log(JSON.parse(res["body"]["group_obj"]));
if(res["body"]["group_obj"]!=null){
load(JSON.parse(res["body"]["group_obj"]));
}
else{
setTimeout(() => {
proj_state = "loaded";
loaded();
}, 1000);
}
}
});
}
</script>
<%- include('../../static/end.ejs',{soc:true}) %>