cdn
<!-- Tyhmeleaf 미적용 -->
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@6.1.15/index.global.min.js"></script>
<!-- Tyhmeleaf 적용 -->
<script th:src="@{https://cdn.jsdelivr.net/npm/fullcalendar@6.1.15/index.global.min.js}"></script>
vo
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class CalendarVo {
private Long calendarNo;
private String title;
private String start1;
private String end;
private boolean allDay;
}
controller
import com.example.practice.service.calendar.CalendarService;
import com.example.practice.vo.calendar.CalendarVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
@RestController
public class CalendarController {
@Autowired
private CalendarService calendarService;
/**
* 캘린더 일정 조회하기
* @return
* @throws Exception
*/
@RequestMapping("/calendarList")
public List<CalendarVo> calendarList() throws Exception{
List<CalendarVo> vo = calendarService.calendarList();
return vo;
}
/**
* 캘린더 일정 추가하기
* @param map
* @return
* @throws Exception
*/
@PostMapping("/calendarSave")
public CalendarVo calendarSave(@RequestBody Map<String, Object> map) throws Exception {
CalendarVo vo = new CalendarVo();
vo.setTitle((String) map.get("title"));
// UTC 시간을 LocalDateTime으로 변환
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
ZonedDateTime startUTC = ZonedDateTime.parse((String) map.get("start"), formatter).withZoneSameInstant(ZoneId.of("Asia/Seoul"));
ZonedDateTime endUTC = map.get("end") != null ? ZonedDateTime.parse((String) map.get("end"), formatter).withZoneSameInstant(ZoneId.of("Asia/Seoul")) : null;
// 한국 시간으로 변환하여 저장
vo.setStart1(startUTC.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
vo.setEnd(endUTC != null ? endUTC.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : null);
vo.setAllDay((Boolean) map.get("allDay"));
// 저장한 일정의 key 값을 포함한 데이터를 다시 반환
calendarService.calendarSave(vo);
return vo;
}
/**
* 캘린더 일정 삭제하기
* @param no
* @return
* @throws Exception
*/
@DeleteMapping("/calendarDelete")
public String calendarDelete(@RequestParam String no) throws Exception{
try{
calendarService.calendarDelete(no);
return "success";
}catch (Exception e){
e.printStackTrace();
return "fail";
}
}
/**
* 캘린더 일정 수정하기
* @param no
* @param map
* @return
*/
@PutMapping("/eventUpdate/{no}")
public String eventUpdate(@PathVariable String no, @RequestBody Map<String, Object> map){
CalendarVo vo = new CalendarVo();
vo.setCalendarNo(Long.valueOf(no));
vo.setTitle((String) map.get("title"));
vo.setStart1(map.get("start1").toString().substring(0, 19));
if(map.get("end") != null){
vo.setEnd(map.get("end").toString().substring(0, 19));
}
vo.setAllDay((Boolean) map.get("allDay"));
try {
calendarService.eventUpdate(vo);
return "success";
} catch (Exception e) {
e.printStackTrace();
return "fail";
}
}
}
service
import com.example.practice.vo.calendar.CalendarVo;
import java.util.List;
public interface CalendarService {
/**
* 캘린더 일정 조회하기
* @return
* @throws Exception
*/
List<CalendarVo> calendarList() throws Exception;
/**
* 캘린더 일정 저장하기
* @param vo
* @throws Exception
*/
void calendarSave(CalendarVo vo) throws Exception;
/**
* 캘린더 일정 삭제하기
* @param no
* @throws Exception
*/
void calendarDelete(String no) throws Exception;
/**
* 캘린더 일정 수정하기
* @param vo
* @throws Exception
*/
void eventUpdate(CalendarVo vo) throws Exception;
}
mapper.class
import com.example.practice.vo.calendar.CalendarVo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface CalendarMapper {
/**
* 캘린더 일정 조회하기
* @return
* @throws Exception
*/
List<CalendarVo> calendarList() throws Exception;
/**
* 캘린더 일정 저장하기
* @param vo
* @throws Exception
*/
void calendarSave(CalendarVo vo) throws Exception;
/**
* 캘린더 일정 삭제하기
* @param no
* @throws Exception
*/
void calendarDelete(String no) throws Exception;
/**
* 캘린더 일정 수정하기
* @param vo
* @throws Exception
*/
void eventUpdate(CalendarVo vo) throws Exception;
}
serviceImpl
import com.example.practice.mapper.calendar.CalendarMapper;
import com.example.practice.service.calendar.CalendarService;
import com.example.practice.vo.calendar.CalendarVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class CalendarServiceImpl implements CalendarService {
@Autowired
private CalendarMapper calendarMapper;
@Override
public List<CalendarVo> calendarList() throws Exception {
return calendarMapper.calendarList();
}
@Override
public void calendarSave(CalendarVo vo) throws Exception {
calendarMapper.calendarSave(vo);
}
@Override
public void calendarDelete(String no) throws Exception {
calendarMapper.calendarDelete(no);
}
@Override
public void eventUpdate(CalendarVo vo) throws Exception {
calendarMapper.eventUpdate(vo);
}
}
mapper.xml - oracle(오라클)
<?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="com.example.practice.mapper.calendar.CalendarMapper">
<!-- 일정 조회하기 -->
<select id="calendarList" resultType="com.example.practice.vo.calendar.CalendarVo">
SELECT
CALENDAR_NO,
CALENDAR_TITLE AS TITLE,
TO_CHAR(CALENDAR_START, 'YYYY-MM-DD"T"HH24:MI:SS') AS START1,
TO_CHAR(CALENDAR_END, 'YYYY-MM-DD"T"HH24:MI:SS') AS END,
ALL_DAY
FROM CALENDAR
</select>
<!-- 일정 저장하기 -->
<!-- 저장하고 생성된 no(key) 값을 return 시킨다 -->
<insert id="calendarSave" parameterType="com.example.practice.vo.calendar.CalendarVo" useGeneratedKeys="true" keyColumn="CALENDAR_NO" keyProperty="calendarNo" >
INSERT INTO CALENDAR(
CALENDAR_NO,
CALENDAR_TITLE,
CALENDAR_START,
CALENDAR_END,
ALL_DAY
) values (
(SELECT NVL(MAX(CALENDAR_NO), 0) + 1 AS CALENDAR_NO FROM CALENDAR),
#{title},
TO_DATE(#{start1}, 'YYYY-MM-DD HH24:MI:SS'),
TO_DATE(#{end}, 'YYYY-MM-DD HH24:MI:SS'),
#{allDay}
)
</insert>
<!-- 일정 삭제하기 -->
<delete id="calendarDelete">
DELETE FROM CALENDAR WHERE CALENDAR_NO = #{no}
</delete>
<!-- 일정 수정하기 -->
<update id="eventUpdate" parameterType="com.example.practice.vo.calendar.CalendarVo">
UPDATE CALENDAR SET
CALENDAR_TITLE = #{title} ,
CALENDAR_START = TO_DATE(#{start1}, 'YYYY-MM-DD"T"HH24:MI:SS') ,
CALENDAR_END = TO_DATE(#{end}, 'YYYY-MM-DD"T"HH24:MI:SS') ,
ALL_DAY = #{allDay}
WHERE CALENDAR_NO = #{calendarNo}
</update>
</mapper>
html
<div class="form-group">
<div id='calendar-container'>
<div id="calendar"></div>
</div>
</div>
여기도 Bootstrap을 사용 중이지만
필요한 건 <div id="calendar"></div> 다
javascript
$(document).ready(function () {
let calendarTag = $('#calendar')[0]; // full-calendar 생성하기
let calendar = new FullCalendar.Calendar(calendarTag, {
height: '550px', // calendar 높이 설정
expandRows: true, // 화면에 맞게 높이 재설정
slotMinTime: '00:00', // Day 캘린더에서 시작 시간
slotMaxTime: '23:59', // Day 캘린더에서 종료 시간
customButtons: { // 사용자가 만드는 버튼
testButton: {
text: "테스트버튼"
}
},
// 해더에 표시할 툴바
headerToolbar: { // customButton 은 left 또는 right 안에 넣으면 적용 된다
left: 'prevYear,prev,next,nextYear today', // today는 , 와 띄어쓰기에 따라서 위치가 바뀐다
// left: 'prev,next,today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
initialView: 'dayGridMonth', // 로드 될때 캘린더 화면 기본 설정
// initialDate: '2024-07-23', // 초기 날짜 설정 (설정하지 않으면 오늘 날짜가 보인다.)
navLinks: true, // 날짜를 선택하면 Day 캘린더나 Week 캘린더로 링크
editable: true, // default : false 이벤트 드래그 등의 편집여부를 설정함
selectable: true, // 일자 드래그 설정
nowIndicator: true, // 현재 시간 마크
dayMaxEvents: true, // 이벤트가 많아지면 + 로 이벤트 표시
locale: 'ko', // 한국어 설정
eventAdd: function (obj) { // 이벤트 추가 시 발생
console.log("eventAdd : " + obj);
},
eventChange: function (obj) { // 이벤트 수정 시 발생
console.log("eventChange : " + obj);
},
eventRemove: function (obj) { // 이벤트 삭제 시 발생
console.log("eventRemove : " + obj);
},
select: function (arg) { // 일자를 드래그하면 실행됨
let title = prompt('일정 입력');
if (title) {
let newData = {
title: title,
start: arg.start,
end: arg.end,
allDay: arg.allDay
}
$.ajax({
url: "/calendarSave",
method: "POST",
dataType: "json",
data: JSON.stringify(newData),
contentType: 'application/json',
success:function (data){
if(data != null){
calendar.addEvent({
id: data.calendarNo,
title: data.title,
start: data.start1,
end: data.end,
allDay: data.allDay,
editable: true // default : false 이벤트 드래그 등의 편집여부를 설정함
});
}
}
})
}
calendar.unselect()
},
eventClick: function (arg) {
// 일정 클릭 시
if (confirm("선택한 일정을 삭제하시겠습니까?")) {
$.ajax({
type: "DELETE",
url: "/calendarDelete",
data: {"no" : arg.event.id},
success: function (data) {
if (data == "success") {
alert("삭제하였습니다.");
arg.event.remove();
}else{
alert("오류가 발생하였습니다");
}
}
})
}
},
eventDrop: function(arg) { // 일정을 이동시킬때, 드래그하여 시작일과 종료일이 변경되는 경우 동작
let event = {
id: arg.event.id,
title: arg.event.title,
start1: arg.event._instance.range.start,
end: arg.event._instance.range.end ? arg.event._instance.range.end : null,
allDay: arg.event.allDay
};
$.ajax({
url: '/eventUpdate/' + arg.event.id,
method: 'PUT',
contentType: 'application/json',
data: JSON.stringify(event)
});
},
eventResize: function(arg) { // 일정의 크기를 변경시킬때 동작(일정을 늘릴때)
let event = {
id: arg.event.id,
title: arg.event.title,
start1: arg.event._instance.range.start,
end: arg.event._instance.range.end ? arg.event._instance.range.end : null,
allDay: arg.event.allDay
};
$.ajax({
url: '/eventUpdate/' + arg.event.id,
method: 'PUT',
contentType: 'application/json',
data: JSON.stringify(event)
});
},
// 이벤트
events: [
$.ajax({
type: "get",
url: "/calendarList",
success: function (data) {
if (data != null) {
for (let i = 0; i < data.length; i++) {
calendar.addEvent({
id: data[i].calendarNo,
title: data[i].title,
start: data[i].start1,
end: data[i].end,
allDay: data[i].allDay,
editable: true // default : false 이벤트 드래그 등의 편집여부를 설정함
})
}
}
}
})
]
});
// 캘린더 랜더링
calendar.render();
});
TEST
headerToolbar 에 설정한 코드로 left center right 에 버튼이 생성된다
1. 클릭하여 일정 입력
2. 날짜를 클릭하여 시간대 설정 또는 All-Day 일정 입력
3. 드래그하여 일정 입력
4. 생성된 일정을 드래그하여 일정 변경(eventDrop)
5. week 에서 일정을 드래그하여 일정 생성하기
6. All-Day 일정을 드래그하여 일정일자의 크기 변경하기(eventResize)
All-Day 일정 bar 오른쪽 끝에 마우스를 가져다 대면
리사이즈 마우스 포인터로 변경되고 일정 일수를 늘리고 줄일 수 있다
시간대가 있는 일정은 일수를 늘릴 수 없고
시작일과 종료일만 드래그(eventDrop)로 변경 가능하다
7. 일정 삭제하기
쉽진 않을 거라 생각했지만 이틀 내내 삽질의 삽질을 무한 반복했다
하나씩 적용해 보고 나에게 맞춰서 코드를 다시 짜고..
어느 정도 기본틀을 맞춰놓으니 이것저것 좀 더 수정하고 싶은 부분이 눈에 띄고 있으나 이 정도로만 만족해야겠다
7. css 추가 , 이벤트에 색상 넣기
css
/* 일요일 날짜: 빨간색 */
.fc-day-sun a {
color: red;
}
/* 토요일 날짜: 파란색 */
.fc-day-sat a {
color: blue;
}
.fc-day-mon a{
color: gray;
}
.fc-day-tue a{
color: gray;
}
.fc-day-wed a {
color: gray;
}
.fc-day-thu a {
color: gray;
}
.fc-day-fri a {
color: gray;
}
.fc-button-primary {
color: red;
}
javascript
// 이벤트
events: [
{
title: "임직원 월례조회",
start: ""+checkYear+"-"+ checkMonth+ "-01T09:00:00",
end: ""+checkYear+"-"+ checkMonth+ "-01T10:00:00",
color: "#4d4d4d", // 이벤트 색상
allDay: false,
editable: false
},
{
title: "코엑스 행사",
start: ""+checkYear+"-"+ checkMonth+ "-10T09:00:00",
end: ""+checkYear+"-"+ checkMonth+ "-12T18:00:00",
color: "#e19999", // 이벤트 색상
textColor : "#ffffff", // 이벤트 타이틀 색상
allDay: false,
editable: true
},
]
'개발 > Spring' 카테고리의 다른 글
[SpringBoot] 메뉴 계층형 구조 만들기(CheckBox, 전체 선택/해제) (0) | 2024.07.31 |
---|---|
[SpringBoot] DataTable 이용하여 추가,수정,삭제 구현하기 (0) | 2024.07.26 |
[SpringBoot] Autocomplete을 이용한 자동완성기능 구현하기 (2) | 2024.07.22 |
[SpringBoot] Chart.js 를 이용하여 실시간 바 차트 구현하기 (0) | 2024.07.17 |
[SpringBoot] Chart.js 를 이용하여 실시간 라인 차트 구현하기 (0) | 2024.07.17 |
댓글