스프링

 

 

결과 화면

 

 

이미지 새창

 

 

 

 

개발환경 :   스프링부트 2.7.9 + mybatis  +mysql + jsp 

 

 

fullcalendar 소스는 다음 링크 주소에 있으며 현재 시점 6.15 이다.

https://github.com/fullcalendar/fullcalendar

 

 

여기 프로젝에서 적용한 fullcalendar 버전은  5.9.0  이다.

https://github.com/braverokmc79/fullcalendar-5.9.0

 

 

 

MYSQL

CREATE TABLE `tbl_schedulemanage` (
  `scheduleId` int(11) NOT NULL AUTO_INCREMENT COMMENT 'schedule번호(PK)',
  `scheduleName` varchar(255) DEFAULT NULL COMMENT '스케줄제목',
  `url` varchar(100) DEFAULT NULL COMMENT '링크주소',
  `textColor` varchar(15) DEFAULT NULL COMMENT '글자색',
  `color` varchar(15) DEFAULT NULL COMMENT '테두리색',
  `backgroundColor` varchar(15) DEFAULT NULL COMMENT '배경색',
  `startDate` varchar(25) DEFAULT NULL COMMENT '시작일',
  `endDate` varchar(25) DEFAULT NULL COMMENT '끝일',
  PRIMARY KEY (`scheduleId`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

 

 

Mybatis

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="패키지명.model.dao.mapper.ScheduleManageMapper">
	
	
	<!-- 관리자 화면일경우 url 생략 -->
	<select id="selectAdminEventList" resultType="패키지명.model.vo.ScheduleManageVO">
		 SELECT
		 	 scheduleid AS "id" , schedulename as "title" ,
	 		if(textColor is null, '#ffffff', textColor ) as textColor, 
		    if(color is null, '#3788d8', color ) as color, 
			if(backgroundColor is null, '#3788d8', backgroundColor ) as backgroundColor		
			, startdate as "start" , enddate AS "end" 
		FROM tbl_schedulemanage
	</select>


	<!-- 5년전 데이터까지만 가져오기 -->
	<select id="selectEventList" resultType="lineage.choco.model.vo.ScheduleManageVO">
		 SELECT
		 	 scheduleid AS "id" , schedulename as "title" ,
	 		if(url is null, '#', url ) as url,
	 		if(textColor is null, '#ffffff', textColor ) as textColor, 
		    if(color is null, '#3788d8', color ) as color, 
			if(backgroundColor is null, '#3788d8', backgroundColor ) as backgroundColor		
			, startdate as "start" , enddate AS "end" 
		FROM tbl_schedulemanage
		
		WHERE  startdate >= date_add(now(), interval -5 year) 
	</select>
	
	
	<insert id="addSchedule" parameterType="패키지명.model.vo.ScheduleManageVO">		
		INSERT INTO tbl_schedulemanage (schedulename, url , textColor,  color ,   backgroundColor ,  startdate, enddate)
					VALUES( #{scheduleName},  #{url} , #{textColor} ,  #{color} , #{backgroundColor} ,  #{startDate}, #{endDate})
	</insert>


	<select id="getEvent" resultType="패키지명.model.vo.ScheduleManageVO">
		SELECT 
		    scheduleid AS "id" , schedulename as "title" ,
	 		if(url is null, '#', url ) as url,
	 		if(textColor is null, '#ffffff', textColor ) as textColor, 
		    if(color is null, '#3788d8', color ) as color, 
			if(backgroundColor is null, '#3788d8', backgroundColor ) as backgroundColor		
			, startdate as "start" , enddate AS "end" 
		FROM tbl_schedulemanage WHERE scheduleid =#{id}
	</select>

	<delete id="deleteSch">
		DELETE FROM tbl_schedulemanage WHERE SCHEDULEID =#{id}
	</delete>

	<update id="updateSch">
		UPDATE tbl_schedulemanage SET	
			 <if test="scheduleName!=null and !scheduleName.equals('') ">
			 	scheduleName= #{scheduleName},
			 </if>
			
			 <if test="url!=null and !url.equals('') ">
			 		url=#{url},
			 </if>
			 <if test="textColor!=null and !textColor.equals('') ">
			 		textColor=#{textColor},
			 </if>	 
			
			  <if test="color!=null and !color.equals('') ">
			 		color=#{color},
			 </if>	
			 <if test="backgroundColor!=null and !backgroundColor.equals('') ">
			 		backgroundColor=#{backgroundColor},
			 </if>	 
			startdate=#{startDate},
			enddate=#{endDate} 
		WHERE scheduleid=#{scheduleId}
	</update>



</mapper>

 

 

ScheduleManageVO

import lombok.Data;
import lombok.ToString;

@Data
@ToString
public class ScheduleManageVO {
	
    private int scheduleId;
    private String scheduleName;
    private String startDate;
    private String endDate;
     
    private String id;
    private String title; //스케줄제목
    private String url;// 링크주소
    private String textColor;  //글자색
    private String color;  //테두리색
    private String backgroundColor;//배경색
    private String start;  //시작일 
    private String end;	//종료일
   
    
   
}

 

 

ScheduleManageService

 

import java.util.List;
import java.util.Map;

import 패키지.model.vo.ScheduleManageVO;

public interface ScheduleManageService {

	public List<ScheduleManageVO> showSchedule() throws Exception;

	public int addSchedule(ScheduleManageVO calendarVO) throws Exception;

	public List<ScheduleManageVO> selectEventList(Map<String, Object> map) throws Exception;

	public ScheduleManageVO getEvent(Map<String, Object> map) throws Exception;

	public int deleteSch(ScheduleManageVO calendarVO) throws Exception;

	public int updateSch(ScheduleManageVO calendarVO) throws Exception;

}

 

 

ScheduleManageServiceImpl

import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Service;

import 패키지.model.dao.mapper.ScheduleManageMapper;
import 패키지.model.vo.ScheduleManageVO;
import 패키지.service.ScheduleManageService;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class ScheduleManageServiceImpl implements ScheduleManageService {

	
	private final ScheduleManageMapper scheduleManageMapper;

	public List<ScheduleManageVO> showSchedule() throws Exception {
		return scheduleManageMapper.showSchedule();
	}

	public int addSchedule(ScheduleManageVO calendarVO) throws Exception {
		return scheduleManageMapper.addSchedule(calendarVO);
	}

	public List<ScheduleManageVO> selectEventList(Map<String, Object> map) throws Exception {
		return scheduleManageMapper.selectEventList(map);
	}

	public ScheduleManageVO getEvent(Map<String, Object> map) throws Exception {
		return scheduleManageMapper.getEvent(map);
	}

	public int deleteSch(ScheduleManageVO calendarVO) throws Exception {
		return scheduleManageMapper.deleteSch(calendarVO);
	}

	public int updateSch(ScheduleManageVO calendarVO) throws Exception {
		return scheduleManageMapper.updateSch(calendarVO);
	}

}

 

 

ScheduleManageMapper

import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Repository;

import 패키지.model.vo.ScheduleManageVO;

@Repository
public interface ScheduleManageMapper {
	
	public List<ScheduleManageVO> showSchedule() throws Exception;

	public int addSchedule(ScheduleManageVO calendarVO) throws Exception;

	public List<ScheduleManageVO> selectEventList(Map<String, Object> map) throws Exception;

	public ScheduleManageVO getEvent(Map<String, Object> map) throws Exception;

	public int deleteSch(ScheduleManageVO calendarVO) throws Exception;

	public int updateSch(ScheduleManageVO calendarVO) throws Exception;
	
	
	
}

 

 

 

 

 

1) 관리자 화면

 

컨트롤

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import 패키지.config.auth.PrincipalDetails;
import 패키지.model.vo.BoardVO;
import 패키지.model.vo.ScheduleManageVO;
import 패키지.service.BoardService;
import 패키지.service.ScheduleManageService;
import lombok.RequiredArgsConstructor;

@Controller
@RequiredArgsConstructor
@RequestMapping("/admin/scheduleManage/")
public class AdminScheduleManageController {


	private final ScheduleManageService calendarService;

	private final BoardService boardService;
	
	

	
	/** 스캐쥴 화면  */
	@GetMapping("list")
	public String scheduleManageList(@AuthenticationPrincipal PrincipalDetails priDetails, Model model) throws Exception {
		model.addAttribute("menuName", "일정관리");
		return "admin/scheduleManage/scheduleManage_list";
	}


	
	@ResponseBody
	@PostMapping("addSchedule")
	public int addSchedule(ScheduleManageVO scheduleManageVO) throws Exception {
		return calendarService.addSchedule(scheduleManageVO);
	}



	/** 스캐쥴 목록 가져오기  */
	@ResponseBody
	@PostMapping("selectEventList")
	public List<ScheduleManageVO> selectEventList(@RequestParam Map<String, Object> map) throws Exception {
		return calendarService.selectEventList(map);
	}

	
	
	@ResponseBody
	@PostMapping("getEvent")
	public ScheduleManageVO getEvent(@RequestParam Map<String, Object> map) throws Exception {
		return calendarService.getEvent(map);
	}

	@ResponseBody
	@PostMapping("deleteSch")
	public int deleteSch(ScheduleManageVO scheduleManageVO) throws Exception {
		return calendarService.deleteSch(scheduleManageVO);
	}

	
	
	@ResponseBody
	@PostMapping("updateSch")
	public int updateSch(ScheduleManageVO scheduleManageVO) throws Exception {
		return calendarService.updateSch(scheduleManageVO);
	}
	
	
	/** 게시판 링크 URL 가져오기  */
	@ResponseBody
	@PostMapping("findBoardTypeByTitleList")
	public List<BoardVO> findBoardTypeByTitleList(@RequestParam Map<String, Object> map) throws Exception {
		return boardService.findBoardTypeByTitleList(map);
	}
	
	

}

 

 

scheduleManage_list.jsp

<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<!-- 부트스트랩 라이브러리 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<!--  fullcalendar 라이브러리  -->
<link href='https://cdn.jsdelivr.net/gh/braverokmc79/fullcalendar-5.9.0@v5.9.0/lib/main.css' rel='stylesheet' />
<!-- daterangepicker 라이브러리  -->
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.css" />
<!-- 커스텀 .css -->
<link href="/resources/lib/fullcalendar/css/scheduleManage_list.css" rel="stylesheet">
</head>
<body>

		<div id='calendar-container'>
			<div id='calendar'></div>
		 </div>
																	
 
	<%@ include file="schedule_manage_modal.jsp" %>
	
	
	<!-- jquery 라이브러리 -->
	<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> 
	
	<!-- 부트스트랩 라이브러리 -->
	<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js" integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous"></script>
	<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"></script>
	
	<!-- 날짜 라이브러리  -->
	<script type="text/javascript" src="//cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
	
	
	<!--  fullcalendar 라이브러리  -->
	<script src='https://cdn.jsdelivr.net/gh/braverokmc79/fullcalendar-5.9.0@v5.9.0/lib/main.js'></script>
	<script src='https://cdn.jsdelivr.net/gh/braverokmc79/fullcalendar-5.9.0@v5.9.0/lib/locales-all.min.js'></script>
	<!-- daterangepicker 라이브러리  -->
	<script type="text/javascript" src="//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.js"></script>
	<!-- 커스텀 js -->
    <script src="/resources/lib/fullcalendar/js/scheduleManage_list.js"></script>
   
</body>
</html>

 

 

scheduleManage_list.css

@charset "utf-8";
#calendar{
   width:80%;
   margin:20px auto;
   margin-bottom:200px;
}
a {
    color: #000000;
    text-decoration: none;
}

/* 드래그 박스의 스타일 */
#external-events {
	position: fixed;
	left: 20px;
	top: 20px;
	width: 100px;
	padding: 0 10px;
	border: 1px solid #ccc;
	background: #eee;
	text-align: left;
}

#external-events h4 {
	font-size: 16px;
	margin-top: 0;
	padding-top: 1em;
}

#external-events .fc-event {
	margin: 3px 0;
	cursor: move;
}

#external-events p {
	margin: 1.5em 0;
	font-size: 11px;
	color: #666;
}

#external-events p input {
	margin: 0;
	vertical-align: middle;
}

#calendar-wrap {
	margin-left: 0px;
}

#calendar1 {
	max-width: 1100px;
	margin: 0 auto;
}
.fc-myCustomButton-button {
/* 	background: #b31515 !important; */
}

.form-group{
	
	margin-bottom: 30px;
}

.fc-event-time, .fc-event-title{
	font-size: 15px;	
}
.empl_nm{
	display: none;
}

.daterangepicker .table-condensed tbody tr td.available:first-child { color: #0d6efd;}
.daterangepicker .table-condensed tbody tr td.available:last-child { color: #f95f53  !important;}
.daterangepicker td.active, .daterangepicker td.active:hover {background-color: #c5daed; border-color: transparent; color: #fff !important;}
.daterangepicker .table-condensed tbody tr td.off {   color: #999  !important;  opacity:0.5;}
.modal .modal-dialog .modal-content .modal-footer {   padding: 15px 31px;display: flex;justify-content: space-around;}

.fc-daygrid-day.fc-day.fc-day-sat.fc-day-past .fc-daygrid-day-top a ,
.fc-daygrid-day.fc-day.fc-day-sat.fc-day-future .fc-daygrid-day-top a
{ color:#2575fc; }     /* 토요일 */

.fc-daygrid-day.fc-day.fc-day-sun.fc-day-past .fc-daygrid-day-top a,
.fc-daygrid-day.fc-day.fc-day-sun.fc-day-future .fc-daygrid-day-top a
{color:#dd3e0e; }/* 일요일 */







 

scheduleManage_list.js

 

다음 사이틀 참조해서  googleCalendarApiKey  구글 api 키값 적용

Spring에서 FullCalendar(풀 캘린더)로 Google(구글) 캘린더 DB 연동하기

 

 

let $g_arg;	//모달창에서 호출하는 함수에서 참조하기 위함)
let $calendar;
let $daterangeStartDate = "";
let $daterangeEndDate = "";
document.addEventListener('DOMContentLoaded', function() {

	//FullCalendar 초기 셋팅 및 데이터 불러오기
	getFullCalendarEvent();
	$('body').on('click', 'button.fc-prev-button', function(e) {
		console.log("prev1");
	});

	$('body').on('click', 'button.fc-next-button', function(e) {
		console.log("next");
	});
});

//FullCalendar 초기 셋팅
function getFullCalendarEvent(currentDatePage) {
	const calendarEl = document.getElementById('calendar');
	$calendar = new FullCalendar.Calendar(calendarEl, {

		googleCalendarApiKey: '구글 APIKEY',
		//className은  되도록 캘린더랑 맞추길
		eventSources: [
			{
				googleCalendarId: 'ko.south_korea#holiday@group.v.calendar.google.com',
				className: '대한민국의 휴일',
				color: '#be5683', //rgb,#ffffff 등의 형식으로 할 수 있다
				//textColor: 'black' 
			},

		],

		customButtons: {
			myCustomButton: {
				text: '일정입력',
				click: function(event) {
					onSelectEvent(event);
				}
			}
		},


		headerToolbar: {
			left: 'prev,next today',
			center: 'title',
			right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek,myCustomButton'
		},
		initialDate: currentDatePage, // 초기 날짜 설정 (설정하지 않으면 오늘 날짜가 보인다.)
		locale: 'ko', // 한국어 설정
		editable: true, // 수정 가능
		droppable: true, // 드래그 가능
		drop: function(arg) { // 드래그 엔 드롭 성공시

		},
		defaultView: 'timeGridWeek',
		navLinks: false, // can click day/week names to navigate views	
		allDaySlot: false,
		eventLimit: true, // allow "more" link when too many events
		//minTime: '10:00:00',
		//maxTime: '24:00:00',
		//contentHeight: 'auto',

		dateClick: function(arg) {
			//해당월  페이지 이동을 위한 날짜가져오기
			var getData = this.getCurrentData();
			var currentDatePage = moment(getData.currentDate).format('YYYY-MM-DD');
			$("#currentDatePage").val(currentDatePage);
			insertModalOpen(arg);

		},


		eventClick: function(info) {
			//여기서 info 가 아니라 event 로 처리해야 함
			event.preventDefault();


			//만약 구글 캘린던라면 링크 이동 중단 처리
			if (info.event.url.includes('https://www.google.com/calendar/')) {
				return;
			}

			//해당월  페이지 이동을 위한 날짜가져오기
			var getData = this.getCurrentData();
			var currentDatePage = moment(getData.currentDate).format('YYYY-MM-DD');
			$("#currentDatePage").val(currentDatePage);

			var url = info.event.url;
			//모달창 호출
			updateModalOpen(info.event.id, url);

		},

		eventAdd: function(obj) { // 이벤트가 추가되면 발생하는 이벤트
			//console.log(" 이벤트가 추가되면 발생하는 이벤트" ,obj);
		},
		eventChange: function(obj) { // 이벤트가 수정되면 발생하는 이벤트
			console.log("1.벤트가 수정되면 발생하는 이벤트 ", obj);
			const scheduleId = obj.event._def.publicId;
			const startDate = moment(obj.event._instance.range.start).format();
			const endDate = moment(obj.event._instance.range.end).format();
			const param = {
				scheduleId,
				startDate,
				endDate
			}
			console.log("2.벤트가 수정되면 발생하는 이벤트 ", obj.event._def.url);
			//만약 구글 캘린던라면 링크  중단 처리
			if (obj.event._def.url.includes('https://www.google.com/calendar/')) {
				alert("지정된 공휴일은 업데이트 처리 될수 없습니다.");
				getFullCalendarEvent();
				return;
			}

			$.ajax({
				url: "/admin/scheduleManage/updateSch",
				type: "POST",
				data: param,
				dataType: "text",
				success: function(result) {
					console.log(" 업데이트 : ", result);
				},
				error: function(result) {
					console.log("error:");
					console.log(result);
				}
			});

		},

		select: function(arg) { // 캘린더에서 드래그로 이벤트를 생성할 수 있다.
			/*   console.log(" 드래그 ", arg)
			  var title = prompt('Event Title:');
			  if (title) {
				calendar.addEvent({
				  title: title,
				  start: arg.start,
				  end: arg.end,
				  allDay: arg.allDay
				})
			  }
			  calendar.unselect() */
		}

	});  //End  ------------  var calendar = new FullCalendar.Calendar(calendarEl,


	//DB에서  데이터 가져오기
	const arr = getCalendarDataInDB();
	$.each(arr, function(index, item) {
		$calendar.addEvent(item);
	});


	$calendar.render();

	$calendar.on('dateClick', function(info) {
		// console.log('clicked on ' + info.dateStr);
	});
	return $calendar;
}

//일정 입력
function onSelectEvent() {
	insertModalOpen("onSelectEvent");
}


//arr 는 테스트용으로 DB 에서 스케즐 데이터를 가져오지 못했을 경우 테스트용 데이터
function getCalendarDataInDB() {
	//arr 임의 데이터
	let arr = [{
		title: 'evt111',
		start: '2023-03-22T10:30:00',
		end: '2023-03-23T10:30:00',
		backgroundColor: "#52cdff",
		color: "#000",
		textColor: "#fff",
		url: "https://daum.net"
	}];

	$.ajax({
		contentType: 'application/json',
		dataType: 'json',
		url: '/admin/scheduleManage/selectEventList',
		type: 'post',
		async: false,
		success: function(res) {

			arr = res;
		},
		error: function(res) {
			console.log(res);
		}
	});
	return arr;
}


// 받은 날짜값을 date 형태로 형변환 해주어야 한다.
function convertDate(date) {
	var date = new Date(date);
	alert(date.yyyymmdd());
}

/*

******************************************************************************************************	
	  여기서 부터 모달 JS
 ******************************************************************************************************
 *
 */
function customDaterangePicker() {

	$('input[name="daterange"]').daterangepicker({
		"showDropdowns": true,
		"showWeekNumbers": true,
		"showISOWeekNumbers": true,
		"timePicker": true,
		"timePicker24Hour": true,
		"timePickerSeconds": true,
		"locale": {
			"format": "YYYY-MM-DD Ah:mm",
			"separator": " - ",
			"applyLabel": "적용",
			"cancelLabel": "취소",
			"fromLabel": "From",
			"toLabel": "To",
			"customRangeLabel": "사용자 지정",
			"weekLabel": "W",
			"daysOfWeek": [
				"일",
				"월",
				"화",
				"수",
				"목",
				"금",
				"토"
			],
			"monthNames": [
				"1월",
				"2월",
				"3월",
				"4월",
				"5월",
				"6월",
				"7월",
				"8월",
				"9월",
				"10월",
				"11월",
				"12월"
			],
			"firstDay": 1
		},
		"autoUpdateInput": false,
		"alwaysShowCalendars": true,
		"startDate": $daterangeStartDate,
		"endDate": $daterangeEndDate,

		"minDate": "2000-12-31",
		"maxDate": "2050-12-31"
	}, function(start, end, label) {


		$("#startDate").val(moment(start).format());
		$("#endDate").val(moment(end).format());
		$("#daterange").val(start.format('YYYY-MM-DD Ah:mm') + "  ~   " + end.format('YYYY-MM-DD Ah:mm'));

	});

}



//이벤트 등록 모달
function insertModalOpen(arg) {
	$(".scheDeleteBtn").css("display", "none");
	$(".schInsertBtn").css("display", "block");
	$(".schUpdateBtn").css("display", "none");

	$(".modal-title").text("일정 등록");
	$("#title").val("");
	$("#url").val("");
	$("#textColor").val("#ffffff");
	$("#color").val("#1466b8");
	$("#backgroundColor").val("#3788d8");


	if (arg == "onSelectEvent") {
		const date1 = new Date();
		arg = {
			dateStr: moment(date1).format('YYYY MM DD')
		}
	}

	$g_arg = arg;

	//초기 해당일 날짜 셋팅
	$daterangeStartDate = arg.dateStr + " AM12:00";
	$daterangeEndDate = arg.dateStr + " PM1:00";
	$("#daterange").val($daterangeStartDate + "  ~   " + $daterangeEndDate);
	const sd1 = new Date(arg.dateStr + "T12:00:00");
	const ed1 = new Date(arg.dateStr + "T13:00:00");
	$("#startDate").val(moment(sd1).format());
	$("#endDate").val(moment(ed1).format());
	$(".daterangepicker_input input[name=daterangepicker_start]").val($daterangeStartDate);
	$(".daterangepicker_input input[name=daterangepicker_end]").val($daterangeEndDate);
	//end - 초기 해당일 날짜 셋팅


	customDaterangePicker();

	$('.insertModal').modal("show");
}



//스케쥴 등록
function insertSch(modal, arg) {
	const scheduleName = $("#title").val();
	const url = $("#url").val();
	const textColor = $("#textColor").val();
	const color = $("#color").val();
	const backgroundColor = $("#backgroundColor").val();
	const startDate = $("#startDate").val();
	const endDate = $("#endDate").val();

	if ($('.insertModal #end').val() <= $('.insertModal #start').val()) {
		alert('종료시간을 시작시간보다 크게 선택해주세요');
		$('.insertModal #end').focus();
		return;
	}
	if ($('.' + modal + ' #title').val() == '') {
		alert('제목을 입력해주세요');
		$("#title").focus();
		return;
	}

	if (startDate == "" || startDate == "Invalid date") {
		alert("시작 날짜를 다시 선택해 주세요.");
		return;
	}

	if (endDate == "" || endDate == "Invalid date") {
		alert("종료 날짜를 다시 선택해 주세요.");
		return;
	}

	const param = {
		scheduleName: scheduleName,
		url: url,
		textColor: textColor,
		color: color,
		backgroundColor: backgroundColor,
		startDate: startDate,
		endDate: endDate
	}

	//스케줄 작성
	$.ajax({
		url: "/admin/scheduleManage/addSchedule",
		type: "POST",
		data: param,
		dataType: "text",
		success: function(result) {
			//console.log(result);

			loadEvents();

		},
		error: function(result) {
			console.log("error:");
			console.log(result);
		}
	});

}

//캘린더 Refresh
function loadEvents() {
	$calendar.destroy();
	const currentDatePage = $("#currentDatePage").val();
	//캘린더 데이터 목록 다시 불러오기
	getFullCalendarEvent(currentDatePage);

	$('.insertModal').modal("hide");
}

//모달 닫기
function closeModal() {
	$('.insertModal').modal("hide");
}

//이벤트 수정 및 삭제 모달
function updateModalOpen(id, url) {

	const currentState = "admin";
	$(".scheDeleteBtn").css("display", "block");
	$(".schInsertBtn").css("display", "none");
	$(".schUpdateBtn").css("display", "block");

	$(".modal-title").text("일정 수정");

	if (currentState == "admin") {

		$.ajax({
			url: "/admin/scheduleManage/getEvent",
			type: "POST",
			data: { id: id },
			dataType: "json",
			success: function(data) {

				const { id, title, url, textColor, color, backgroundColor, start, end } = data;

				$("#scheduleId").val(id);
				$("#title").val(title);
				$("#url").val(data.url);
				$("#textColor").val(textColor);
				$("#color").val(color);
				$("#backgroundColor").val(backgroundColor);

				//초기 해당일 날짜 셋팅
				$("#startDate").val(start);
				$("#endDate").val(end);


				$daterangeStartDate = moment(start).format('YYYY-MM-DD Ah:mm');
				$daterangeEndDate = moment(end).format('YYYY-MM-DD Ah:mm');
				$("#daterange").val($daterangeStartDate + "  ~   " + $daterangeEndDate);

				$(".daterangepicker_input input[name=daterangepicker_start]").val($daterangeStartDate);
				$(".daterangepicker_input input[name=daterangepicker_end]").val($daterangeEndDate);
				//end -  해당일 날짜 셋팅
				//date picker 호출
				customDaterangePicker();
				$('.insertModal').modal("show");
			},
			error: function(result) {
				console.log("error:");
				console.log(result);
			}
		});


	} else {
		//구글 이동
		//window.open(url);
	}
}


//삭제 처리 
function deleteSch() {
	const id = $("#scheduleId").val();
	if (confirm("정말 삭제 하시겠습니까?")) {
		$.ajax({
			url: "/admin/scheduleManage/deleteSch",
			type: "POST",
			data: { id: id },
			dataType: "json",
			success: function(result) {
				// console.log(result);
				if (result == 1) {
					loadEvents();
				} else {
					console.log("error");
				}
			},
			error: function(result) {
				console.log("error:");
				console.log(result);
			}
		});

	}

}



//스케쥴 수정
function updateSch(modal, arg) {
	const scheduleId = $("#scheduleId").val();
	const url = $("#url").val();
	const textColor = $("#textColor").val();
	const color = $("#color").val();
	const backgroundColor = $("#backgroundColor").val();
	const scheduleName = $("#title").val();
	const startDate = $("#startDate").val();
	const endDate = $("#endDate").val();


	if ($('.insertModal #end').val() <= $('.insertModal #start').val()) {
		alert('종료시간을 시작시간보다 크게 선택해주세요');
		$('.insertModal #end').focus();
		return;
	}
	if ($('.' + modal + ' #title').val() == '') {
		alert('제목을 입력해주세요');
		$("#title").focus();
		return;
	}

	if (startDate == "" || startDate == "Invalid date") {
		alert("시작 날짜를 다시 선택해 주세요.");
		return;
	}

	if (endDate == "" || endDate == "Invalid date") {
		alert("종료 날짜를 다시 선택해 주세요.");
		return;
	}

	const param = {
		scheduleId: scheduleId,
		scheduleName: scheduleName,
		url: url,
		textColor: textColor,
		color: color,
		backgroundColor: backgroundColor,
		startDate: startDate,
		endDate: endDate
	}


	$.ajax({
		url: "/admin/scheduleManage/updateSch",
		type: "POST",
		data: param,
		dataType: "text",
		success: function(result) {
			loadEvents();
		},
		error: function(result) {
			console.log("error:");
			console.log(result);
		}
	});

}



/*

******************************************************************************************************	
	  여기서 부터는 fullcalendar 과 상관없는  게시판 목록 가져오기
 ******************************************************************************************************
 *
 */

function findBoardTypeByTitleList(event) {
	const boardType = event.value;

	if (boardType) {
		$.ajax({
			type: "POST",
			url: "/admin/scheduleManage/findBoardTypeByTitleList",
			data: { boardType },
			success: function(res) {

				console.log(res);
				const titleList = res.map(board => {
					console.log(board.agoTime);
					let agoTime = "";
					if (parseInt(board.agoTime) >= 1) {
						agoTime = "[" + board.agoTime + "일전]"
					} else {
						agoTime = "[오늘]";
					}

					let title = "";
					if (board.title.length >= 20) {
						title = board.title.substring(0, 20) + "...";
					} else {
						title = board.title;
					}

					title = title + " " + agoTime;
					return ("<option  value='/board/" + boardType + "/read/" + board.bno + "' >" + title + "</option>")
				});

				$("#boardTitleList").html(titleList);
				setBoardLink();
			},
			error: function(err) {
				console.error("에러 : ", err);
			}
		})
	}
}

function setBoardLink() {
	const url = $("#boardTitleList").val();
	$('#url').val(url);
}

 

 

 

 

 

schedule_manage_modal.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<div class="modal fade insertModal" id="myModal">
    <div class="modal-dialog">
      <div class="modal-content">
      
        <!-- Modal Header -->
        <div class="modal-header">
          <h2 class="modal-title text-center" style="width: 100%; font-size: 1.7rem"></h2>
          <button type="button" class="close" onclick="closeModal()">&times;</button>
        </div>
        
        <!-- Modal body -->
        <div class="modal-body">
          <div class="form-group empl_nm">
			<label for="empl_nm">scheduleId:</label>
			<input type="text" class="form-control" id="scheduleId"  name="scheduleId" readonly="readonly">
		  </div>
		  
   		  <br>
   		  	
			<div class="form-group">	
				<label for="empl_nm">날짜:</label>	
				<input type="text" name="daterange" id="daterange"   class="form-control" /> 
			</div>
   		  <div class="form-group empl_nm">
			<label for="date">시작일:</label>
			<input type="text" class="form-control"  id="startDate" name="startDate">
		  </div>	
	
	      <div class="form-group empl_nm">
			<label for="date">종료일:</label>
			<input type="text" class="form-control"  id="endDate" name="endDate">
		  </div>	
   		  
   		  
          <div class="form-group">
			<label for="title">제목:</label>
			<input type="text" class="form-control" placeholder="" id="title" maxlength="30">
		  </div>
		

	
		<div class="form-group">
			<label for="title">게시판 URL 선택:</label>
			<select onchange="findBoardTypeByTitleList(this)" class="form-control">
				<option value="">게시판을 선택해 주세요.</option>
				<option value="lineage_news">소식</option>
				<option value="lineage_stats">서버통계</option>
				<option value="free">자유게시판</option>
				<option value="broadcast">방송정보</option>
				<option value="screen_capture">스크린샷</option>
				<option value="events">스크린샷</option>
			</select>
		
			<select id="boardTitleList" class="form-control" onchange="setBoardLink()">
				
			</select>
		</div>
	

	
		<div class="form-group">
			<label for="url">url : </label>
			<input type="url" class="form-control" placeholder="링크주소" name="url" id="url" >
		</div>
	
	
		<div class="form-group">
			<label for="textColor">글자색 : </label>
			<input type="color" class="form-control" name="textColor" id="textColor" value="#ffffff" >
		</div>	

		<div class="form-group">
			<label for="color">테두리색 : </label>
			<input type="color" class="form-control" name="color" id="color"   value="#1466b8">
		</div>	
	
		<div class="form-group">
			<label for="backgroundColor">배경색 : </label>
			<input type="color" class="form-control" name="backgroundColor" id="backgroundColor"   value="#3788d8">
		</div>	
	


        <!-- Modal footer -->
        <div class="modal-footer text-center">
		  <button type="button" class="btn btn-danger  scheDeleteBtn" onclick="deleteSch()"   >삭제</button>
		  <button type="button" class="btn btn-warning schInsertBtn" onclick="insertSch('insertModal', $g_arg)">등록</button>
		  <button type="button" class="btn btn-warning schUpdateBtn" onclick="updateSch('insertModal', $g_arg)" >수정</button>
        </div>
        
      </div>
    </div>
  </div>
</div>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2) 유저화면

 

컨트롤

import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import 패키지.model.vo.ScheduleManageVO;
import 패키지.service.ScheduleManageService;
import lombok.RequiredArgsConstructor;

@Controller
@RequestMapping("/schedule/")
@RequiredArgsConstructor
public class ScheduleController {


	private final ScheduleManageService calendarService;

	
	/** 목록 */
	@GetMapping("list")
	public String scheduleList( Model model) throws Exception {
		return "web/schedule/schedule_list";
	}
	
	

	
	@ResponseBody
	@GetMapping("selectEventList")
	public List<ScheduleManageVO> selectEventList(@RequestParam Map<String, Object> map) throws Exception {
		return calendarService.selectEventList(map);
	}

	
	
	
}

 

 

 

schedule_list.jsp

<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="ko">
<head>
<!-- 부트스트랩 라이브러리 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<!--  fullcalendar 라이브러리  -->
<link href='https://cdn.jsdelivr.net/gh/braverokmc79/fullcalendar-5.9.0@v5.9.0/lib/main.css' rel='stylesheet' />
<!-- daterangepicker 라이브러리  -->
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.css" />
<!-- 커스텀 .css -->
<link href="/resources/lib/fullcalendar/css/scheduleManage_list.css" rel="stylesheet">
</head>
<body>

		<div id='calendar-container'>
			<div id='calendar'></div>
		 </div>
																	
 
	<%@ include file="schedule_manage_modal.jsp" %>
	
	
	<!-- jquery 라이브러리 -->
	<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> 
	
	<!-- 부트스트랩 라이브러리 -->
	<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js" integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous"></script>
	<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"></script>
	
	<!-- 날짜 라이브러리  -->
	<script type="text/javascript" src="//cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
	
	
	<!--  fullcalendar 라이브러리  -->
	<script src='https://cdn.jsdelivr.net/gh/braverokmc79/fullcalendar-5.9.0@v5.9.0/lib/main.js'></script>
	<script src='https://cdn.jsdelivr.net/gh/braverokmc79/fullcalendar-5.9.0@v5.9.0/lib/locales-all.min.js'></script>
	<!-- daterangepicker 라이브러리  -->
	<script type="text/javascript" src="//cdn.jsdelivr.net/bootstrap.daterangepicker/2/daterangepicker.js"></script>
	<!-- 커스텀 js -->
    <script src="/resources/lib/fullcalendar/js/schedule_list.js"></script>
   
</body>
</html>

 

 

schedule_list.js

let $calendar;
document.addEventListener('DOMContentLoaded', function() {
	//FullCalendar 초기 셋팅 및 데이터 불러오기
	getFullCalendarEvent();
});

//FullCalendar 초기 셋팅
function getFullCalendarEvent() {
	const calendarEl = document.getElementById('calendar');
	$calendar = new FullCalendar.Calendar(calendarEl, {

		googleCalendarApiKey: '구글 APIKEY',
		//className은  되도록 캘린더랑 맞추길
		eventSources: [
			{
				googleCalendarId: 'ko.south_korea#holiday@group.v.calendar.google.com',
				className: '대한민국의 휴일',
				color: '#be5683', //rgb,#ffffff 등의 형식으로 할 수 있다
				//textColor: 'black' 
			},

		],
		headerToolbar: {
			left: 'prev,next today',
			center: 'title',
			right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek,myCustomButton'
		},
		//initialDate: currentDatePage, // 초기 날짜 설정 (설정하지 않으면 오늘 날짜가 보인다.)
		locale: 'ko', // 한국어 설정
		editable: false, // 수정 가능
		droppable: false, // 드래그 가능
		drop: function(arg) { // 드래그 엔 드롭 성공시
		},
		defaultView: 'timeGridWeek',
		navLinks: false, // can click day/week names to navigate views	
		allDaySlot: false,
		eventLimit: true, // allow "more" link when too many events
		dateClick: function(arg) {
			
		},
		eventClick: function(info) {
			//여기서 info 가 아니라 event 로 처리해야 함
			event.preventDefault();
			//만약 구글 캘린던라면 링크 이동 중단 처리
			if (info.event.url.includes('https://www.google.com/calendar/')) {
				return;
			}
			

			const url = info.event.url;
			if(url!="" || url!="#"){
				location.href=url;
			}
		},
	});  

	//DB에서  데이터 가져오기
	const arr = getCalendarDataInDB();
	$.each(arr, function(index, item) {
		$calendar.addEvent(item);
	});


	$calendar.render();
	return $calendar;
}



//arr 는 테스트용으로 DB 에서 스케즐 데이터를 가져오지 못했을 경우 테스트용 데이터
function getCalendarDataInDB() {
	//arr 임의 데이터
	let arr = [{
		title: 'evt111',
		start: '2023-03-22T10:30:00',
		end: '2023-03-23T10:30:00',
		backgroundColor: "#52cdff",
		color: "#000",
		textColor: "#fff",
		url: "https://daum.net"
	}];

	$.ajax({
		contentType: 'application/json',
		dataType: 'json',
		url: '/schedule/selectEventList',
		type: 'GET',
		async: false,
		success: function(res) {

			arr = res;
		},
		error: function(res) {
			console.log(res);
		}
	});
	return arr;
}




 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

행운에 모든 것을 맡긴 채 의지해서는 안된다. -탈무드-

댓글 ( 5)

댓글 남기기

작성