본문 바로가기

프로젝트 개발기/Status 200 ( Team Project )

8. TEAM 프로젝트: 캘린더 기능 구현 - 스케줄 (2)


상세한 개발 내역을 작성할려고 했으나, 여러 번의 디버그가 있었고 개발 단계에서 변경되는 점 또한 많았다. 

때문에 완성된 캘린더를 기능 별로 정리하고, 개선점을 작성하려고 한다. 

(TimeLine에 작성해 봤으나 글이 한눈에 들어오지 않는다는 단점이 있어서 방법을 바꿨다.)

 


1. 스케줄 추가 기능: 신청 양식

 

스케줄을 추가하기 위해서는 다양한 정보를 삽입해야한다. 

때문에 별도의 폼을 구현하여 해당 정보를 가져오고, 전송할 수 있어야 한다. 

일간 모양과의 호환을 위하여 날짜와 일에 대한 데이터를 수정할 수 있도록 했다. 

 

셀렉트로 시간을 설정하면 해당 설정에 따라 설정 불가능한 시간을 안보이게 설정하고, '종일'을 누르면 종 00시~23시 45분까지 설정되게 만들었다.

 

// 스케줄 Form에서 추가 버튼을 누를 경우 
let scheduleFormBtn = document.getElementsByClassName("scheduleFormSubmit")[0];
scheduleFormBtn.addEventListener("click", function (){
    addGroupSchedule();
    visibleScheduleForm();
})​

위와 같이 추가 버튼에 대한 이벤트를 '제출'에 부여하였다. 

 

let scheduleFormAlldayBtn = document.getElementsByClassName("scheduleFormAllday")[0];

scheduleFormAlldayBtn.addEventListener("click", function(){
    let value = scheduleFormAlldayBtn.getElementsByClassName("scheduleFormAlldayInput")[0];
    let btn = document.getElementsByClassName("scheduleFormAllday")[0];
    let sels = document.getElementsByClassName("scheduleFormStartTime")[0];
    let sele = document.getElementsByClassName("scheduleFormEndTime")[0];
    let datestart = document.getElementsByClassName("scheduleFormStart")[0];
    let dateend = document.getElementsByClassName("scheduleFormEnd")[0];

    if(value.value=="false"){
        value.setAttribute("value", "true");
        sels.setAttribute("style", "visibility: hidden;");
        sele.setAttribute("style", "visibility: hidden;");
        sels.setAttribute("value", "00:00")
        sels.value="00:00";
        sele.setAttribute("value", "23:45")
        sele.value="23:45";
        btn.setAttribute("style", "background-color: #7dc5ea")
    }
    else{
        value.setAttribute("value", "false");
        sels.removeAttribute("style");
        sele.removeAttribute("style");
        btn.removeAttribute("style");
    }
});

let scheduleFormStartTimeBtn = document.getElementsByClassName("scheduleFormStartTime")[0];
scheduleFormStartTimeBtn.addEventListener("change", function(){
    let scfet = event.target;
    let scfst = document.getElementsByClassName("scheduleFormEndTime")[0];
    let options = scfst.getElementsByTagName("option");
    let tempdate = scfst.value;
    console.log(tempdate);
    let time = scfet.value;
    let hour = time.substring(0,2);
    let min = time.substring(3,5);
    let tempflag = false;

    for(let i = 0; i < options.length; i++){
        let temptime = options[i].value;
        let temphour = temptime.substring(0,2);
        let tempmin = temptime.substring(3,5);
        if(temphour==hour){
            if(tempmin>=min){
                options[i].setAttribute("style", "display:block;");
            }
            else if(tempmin<min){
                options[i].setAttribute("style", "display:none;");
            }
        }
        else if(temphour<hour){
            options[i].setAttribute("style", "display:none;");
        }
        else{
            options[i].setAttribute("style", "display:block;");
        }
        if(tempdate<scfet.value&&tempflag==false){
            let str = temphour+":"+tempmin
            scfst.setAttribute("value", str);
            scfst.value = str;

            if(str==scfet.value){
                tempdate = true;
            }
        }
    }
});

let scheduleFormEndTimeBtn = document.getElementsByClassName("scheduleFormEndTime")[0];
scheduleFormEndTimeBtn.addEventListener("change", function(){
    let scfet = event.target;
    let scfst = document.getElementsByClassName("scheduleFormStartTime")[0];
    let options = scfst.getElementsByTagName("option");

    let time = scfet.value;
    let hour = time.substring(0,2);
    let min = time.substring(3,5);

    for(let i = 0; i < options.length; i++){
        let temptime = options[i].value;
        let temphour = temptime.substring(0,2);
        let tempmin = temptime.substring(3,5);
        if(temphour==hour){
            if(tempmin<=min){
                options[i].setAttribute("style", "display:block;");
            }
            else if(tempmin>min){
                options[i].setAttribute("style", "display:none;");
            }
        }
        else if(temphour>hour){
            options[i].setAttribute("style", "display:none;");
        }
        else{
            options[i].setAttribute("style", "display:block;");
        }
    }
});

 

위의 코드는 옆과 같은 역할을 한다.

 

종일을 누르면 셀렉트 값이 변경되고, 셀렉트 또한 선택한 값에 따라 범위가 변경된다. 

 

 

 

 

 

 

2. 스케줄 상세 정보

스케줄 막대로 데이터를 표시하면 시간, 그룹, 스케줄 데이터 등에 대한 데이터를 확인할 수 없다. 때문에 스케줄 클릭시 이를 확인할 수 있도록 상세 정보 창을 구현해야 한다.

호버 처리하여 보이도록 할 수 있으나, 데이터 수정이나 삭제가 필요할 때 호버처리를 하면 오히려 창이 사라져서 번거로운 작업을 진행할 가능성이 있다. (한다면 클릭과 호버를 모두 해야한다.)

 

상세 정보를 만든다면 다음 기능이 필요하다. 

 

  • 스케줄의 상세 정보 표시 기능
  • 스케줄의 수정자 권한에 따른 수정 및 삭제 기능 
  • 스케줄 클릭할 때 스케줄 데이터 표시하기
  • 스케줄 외의 요소를 클릭하면 스케줄 추가 표시하기

 

1) 자세한 스케줄 정보 확인

// 스케줄 자세한 정보 창을 표현
// 해당 div를 띄워서 클릭한 곳 위에 표현해야함 
function scheduleDetailInfo(){
    let target = event.target;

    if(target.childElementCount!=0){

    }
    else if(target.childElementCount==0){
        target = target.parentElement;
    }

    let Infos = target.getElementsByClassName("scheduleInfos")[0];
    let num = Infos.getElementsByClassName("scheduleNum")[0].value;
    let title = Infos.getElementsByClassName("scheduleTitle")[0].value;
    let content = Infos.getElementsByClassName("scheduleContent")[0].value;
    let start = Infos.getElementsByClassName("scheduleStart")[0].value;
    let end = Infos.getElementsByClassName("scheduleEnd")[0].value;
    let color = Infos.getElementsByClassName("scheduleColor")[0].value;
    let groupnum = Infos.getElementsByClassName("groupNum")[0].value;
    let groupname = Infos.getElementsByClassName("groupName")[0].value;

    let data = {
        num: num,
        title: title,
        content: content,
        start: start,
        end: end,
        color: color,
        groupnum: groupnum,
        groupname: groupname
    }
    tempData = data;

    viewScheduleDetail(data);
    visibleScheduleForm(); // 스케줄 보일지 말지를 확인하는 함수
    quitScheduleDetail();
}

// 스케줄 자세한 정보 창 ELEMENT 만들기
function viewScheduleDetail(data){
    console.log(data);
    let target = event.target;
    let p = document.getElementsByClassName("schedulInfoArea")[0];

    let fixBtn = document.getElementsByClassName("schedulInfoFix")[0];
    let delBtn = document.getElementsByClassName("schedulInfoDelete")[0];
    let offBtn = document.getElementsByClassName("schedulInfoQuit")[0];

    let groupname = document.getElementsByClassName("schedulInfoGroupName")[0];
    let groupnum = document.getElementsByClassName("schedulInfoArea")[0];
    let groupmodifier = document.getElementsByClassName("schedulInfoArea")[0];// 검증필요

    let allDay = document.getElementsByClassName("blockBoxAllDay")[0];
    let schedulenum = document.getElementsByClassName("schedulInfoScheduleNum")[0];
    let color = document.getElementsByClassName("schedulInfoColor")[0];
    let title = document.getElementsByClassName("schedulInfoTitle")[0];
    let content = document.getElementsByClassName("schedulInfoContentText")[0];
    let scStartDay = document.getElementsByClassName("schedulInfoStartDay")[0];
    let scStartTime = document.getElementsByClassName("schedulInfoStartTime")[0];
    let scEndDay = document.getElementsByClassName("schedulInfoEndDay")[0];
    let scEndTime = document.getElementsByClassName("schedulInfoEndTime")[0];

    groupname.innerHTML = data.groupname;
    groupnum.setAttribute("value", data.groupnum);

    schedulenum.setAttribute("value", data.num);
    color.setAttribute("value", data.color);
    color.innerHTML = data.color;
    title.innerHTML = data.title;
    content.innerHTML = data.content;

    let startDay = data.start.substring(0,10);
    let startTime = data.start.substring(11,20);
    let endDay = data.end.substring(0,10);
    let endTime = data.end.substring(11,20);

    scStartDay.innerHTML = startDay;
    scStartTime.innerHTML = startTime;
    scEndDay.innerHTML = endDay;
    scEndTime.innerHTML = endTime;

    let modifier = "notModifier"; 
    let groups = document.getElementsByClassName("groupDataInfos");

    for(let i = 0; i < groups.length; i++){
        let gn = groups[i].getElementsByClassName("groupDataNum")[0];
        if(gn.value==data.groupnum){
            let md = groups[i].getElementsByClassName("groupDataModifierListName");

            for(let j = 0; j <md.length; j++){
                let str = (md[j].innerHTML+"").replace(")", ' ');
                let modifiId = str.split("(");
                let strId = modifiId[1].trim();
                userKey.trim();

                if(strId==userKey){
                    modifier = strId;
                }
            }
        }
    }

    if(startTime=="00:00"&&endTime=="23:45"){
        scEndTime.setAttribute("style", "visibility: hidden;");
        scStartTime.setAttribute("style", "visibility: hidden;");
        allDay.setAttribute("style", "visibility: visible;");		
    }
    else{
        scEndTime.removeAttribute("style");
        scStartTime.removeAttribute("style");
        allDay.removeAttribute("style");
    }

    if(modifier==userKey){
        fixBtn.removeAttribute("style");
        fixBtn.addEventListener("click", scheduleDetailInfoFix);
        delBtn.removeAttribute("style");
        delBtn.addEventListener("click", delGroupSchedule);
    }
    else{
        fixBtn.setAttribute("style", "visibility: hidden;");
        fixBtn.removeEventListener("click", scheduleDetailInfoFix);
        delBtn.setAttribute("style", "visibility: hidden;");
        delBtn.removeEventListener("click", delGroupSchedule);
    }
}

// 스케줄을 누르면 스케줄 추가 양식이 같이 표시된다. 
// (이는 달력 영역에 이벤트 리스너가 설정되서이다. 때문에 이를 강제로 종료해준다.)
function quitScheduleDetail(){
    let area = document.getElementsByClassName("schedulInfoArea")[0];
    let flag = document.getElementsByClassName("scAreaFlag")[0];

    if(flag.value=='false'){
        area.setAttribute("style", "display:block;");
        flag.setAttribute("value", "true");
    }
    else{
        area.removeAttribute("style");
        flag.setAttribute("value", "false");
    }

    if(flag=="true"){
        visibleScheduleForm();
    }
}

 

2) 스케줄 권한자 기능

그룹 수정 권한자에 저장된 데이터를 기반으로 스케줄의 수정자 여부를 판단한다.

 

수정자가 일치하는 경우, 수정 및 삭제가 가능한 버튼이 스케줄 정보에 표기되는 방식으로 구현하였다. 

 

권한자가 아니면 스케줄 세부 정보 창의 삭제 및 수정 버튼이 활성화 되지 않는다. 

수정을 누르면 스케줄 입력 창으로 변경된다. 

 

 

3) 스케줄 세부 정보에서 삭제 혹은 추가 혹은 종료

// 스케줄 수정 기능
// 스케줄 수정을 위한 데이터를 수집함 
// 펑션으로 데이터를 가져오소 설정함 
// 전역의 템프 데이터를 가져와서 만들어진 스케줄 수정 항목에 세팅하는 용도임
function scheduleDetailInfoFix(){
    let data = tempData;

    let startDay = data.start.substring(0,10);
    let startTime = data.start.substring(11,20);

    let endDay = data.end.substring(0,10);
    let endTime = data.end.substring(11,20);

    let form = document.getElementsByClassName("scheduleForm")[0];
    let formnum = form.getElementsByClassName("scheduleFormNum")[0];
    let formtitle = form.getElementsByClassName("scheduleFormTitle")[0];
    let formcontent = form.getElementsByClassName("scheduleFormContent")[0];
    let formstart = form.getElementsByClassName("scheduleFormStart")[0];
    let formstarttime = form.getElementsByClassName("scheduleFormStartTime")[0];
    let formend = form.getElementsByClassName("scheduleFormEnd")[0];
    let formendtime = form.getElementsByClassName("scheduleFormEndTime")[0];
    let formcolor = form.getElementsByClassName("scheduleFormColor")[0];
    let formgroupSelect = form.getElementsByClassName("scheduleFormGroupSelect")[0];
    let options = formgroupSelect.getElementsByClassName("scheduleFormGroupSelectOption");

    formnum.setAttribute("value", data.num);
    formtitle.setAttribute("value", data.title);
    formcontent.setAttribute("value", data.content);
    formstart.setAttribute("value", startDay);
    formstart.value=startDay;
    formstarttime.setAttribute("value", startTime);
    formstarttime.value=startTime;
    formend.setAttribute("value", endDay);
    formendtime.setAttribute("value", endTime);
    formendtime.value=endTime;
    formend.value=endDay;
    formcolor.setAttribute("value", data.color);

    for(let i = 0; i<options.length; i++){
        if(options[i].value==data.groupnum){
            options[i].setAttribute("selected", "true");
        }
    }
    quitScheduleDetail();

    let flag = document.getElementsByClassName("scheduleFlag")[0].value;
    console.log(flag);
    if(flag=="false"){
        visibleScheduleForm();
    }
}
// 삭제는 delGroupSchedule()
// 종료는 quitScheduleDetail() 
// 위의 함수는 이전에 소개된 적이 있음