freckie

Add: first version

1 +<!DOCTYPE html>
2 +<html>
3 + <head>
4 + <base target="_top">
5 + </head>
6 + <body>
7 + <form>
8 + <input type="hidden" id="errorCode" value="error-0">
9 + <p>
10 + <strong>교수명</strong>
11 + <input type="text" id="formInputProfName" name="name" value="김가나">
12 + </p>
13 + <p>
14 + <strong>강좌코드</strong>
15 + <input type="text" id="formInputClassCode" name="classcode" value="CEEEE">
16 + </p>
17 +
18 + <p>
19 + <strong>강의명</strong>
20 + <input type="text" id="formInputClassName" name='classname' value="공학과경영">
21 + </p>
22 + <p>
23 + <strong>정원</strong>
24 + <input type="number" id="formInputNumPeople" name="num-people" value="1" min="1">
25 + </p>
26 + <p>
27 + <strong>강의실</strong>
28 + <input type="text" id="formInputClassRoom" name="classroom" value="멀303" placeholder="셀을 선택하면 자동으로 입력됩니다." disabled>
29 + </p>
30 + <p>
31 + <strong>선택 시간</strong>
32 + <input type="text" id="formInputTime" name="time" value="" placeholder="셀을 선택하면 자동으로 입력됩니다." disabled>
33 + </p>
34 + <p>
35 + <input type="button" value="제출" id="formSubmitBtn">
36 + </p>
37 + </form>
38 + <?!= HtmlService.createHtmlOutputFromFile('SidebarJS').getContent(); ?>
39 + </body>
40 +</html>
1 +<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
2 +<script>
3 + /**
4 + * Run initializations on sidebar load.
5 + */
6 + $(function() {
7 + $('#formSubmitBtn').click(submit);
8 +
9 + // Assign handler functions to sidebar elements here, if needed.
10 +
11 + // Call the server here to retrieve any information needed to build
12 + // the dialog, if necessary.
13 +
14 + // Start polling for updates
15 + poll(1000);
16 + });
17 +
18 + /**
19 + * Poll a server-side function at the given interval, to have
20 + * results passed to a successHandler callback.
21 + *
22 + * https://stackoverflow.com/a/24773178/1677912
23 + *
24 + * @param {Number} interval (optional) Time in ms between polls.
25 + * Default is 1s (1000ms)
26 + */
27 + function poll(interval) {
28 + interval = interval || 1000;
29 + //interval = 500;
30 + setTimeout(function() {
31 + google.script.run
32 + .withSuccessHandler(updateFormValues)
33 + .withFailureHandler(function (error) { //To-do! Failuer처리는 어떻게?
34 + var div = document.getElementById('error');
35 + div.innerHTML = "ERROR: " + error.message;
36 + })
37 + .getRange();
38 + }, interval);
39 + };
40 +
41 +
42 + function validateRange(range, topHeader) {
43 + // domain내의 범위인가 (top header제외)
44 + const top = 2;
45 + const outOfRange = 34;
46 + if (top >= range.row || outOfRange <= range.row)
47 + return {code: "error-04"};
48 +
49 + //range column이 left header와 right header사이에 있는가
50 + const leftHeader = 2;
51 + const rightHeader = 35;
52 + if (range.col <= leftHeader || range.col >= rightHeader){ //To-do! 고정값으로 할 것인가, sheet인식해서 값 변동시킬 것인가.
53 + return {code: "error-02"};
54 + }
55 +
56 + //range가 1열로 이루어져있는가
57 + if (range.width != 1)
58 + return {code: "error-01"};
59 +
60 + // 이미 예약된 항목과 겹치는가 //To-do! 백엔드에서 동시성 제어하도록 전환할 것
61 + for (var i = 0; i < range.height; ++i) {
62 + for (var j = 0; j < range.width; ++j) {
63 + if (range.values[i][j] !== ""){
64 + return {code: "error-05"};
65 + }
66 + }
67 + }
68 +
69 + //수용인원을 초과하는가
70 + var lastIdx = topHeader.lastIndexOf("명")
71 + var startIdx = topHeader.lastIndexOf("\n", lastIdx) + 1;
72 + var capacity = parseInt(topHeader.substring(startIdx, lastIdx));
73 + if (capacity < $('input[name=num-people]').val())
74 + return {code: "error-03"};
75 +
76 + return {code: ""};
77 + }
78 +
79 +
80 +
81 +
82 +
83 + // param: rangeInfo -> [{int col, int width, int height}, String topHeader's value (like 전정\n205\n202명)]
84 + function updateFormValues([range, topHeader, date]) {
85 + var ret = validateRange(range, topHeader);
86 + if (ret.code === "") {
87 + var parsed = topHeader.split("\n");
88 + var classroom = parsed[0] + " " + parsed[1];
89 +
90 + $('input[name=classroom]').val(classroom);
91 +
92 + var start = 9 * 60 + 30 * (range.row - 3);
93 + var stop = start + 30 * range.height;
94 + var startStr = parseInt(start/60).toString() + ":" + ((start%60)<10 ? '0' + (start % 60).toString() : (start % 60).toString());
95 + var stopStr = parseInt(stop/60).toString() + ":" + ((stop%60)<10 ? '0' + (stop % 60).toString() : (stop % 60).toString());
96 + var timeInterval = startStr + "~" + stopStr;
97 + $('input[name=time]').val(date + " " + timeInterval);
98 + $('#errorCode').val(ret.code);
99 + poll(1000);
100 + return;
101 +
102 + }
103 + $('input[name=classroom]').val("");
104 + $('input[name=time]').val("");
105 + $('#errorCode').val(ret.code);
106 + poll(1000);
107 + };
108 +
109 + function submit() {
110 + // 변수들
111 + var inputValues = {
112 + profName: $('#formInputProfName').val(),
113 + classCode: $('#formInputClassCode').val(),
114 + className: $('#formInputClassName').val(),
115 + numPeople: $('#formInputNumPeople').val(),
116 + classRoom: $('#formInputClassRoom').val(),
117 + time: $('#formInputTime').val()
118 + };
119 + var errorCode = $('#errorCode').val();
120 +
121 + google.script.run
122 + .withSuccessHandler(function () {
123 + })
124 + .withFailureHandler(function (error) {
125 + console.log('[submit() Error]', error);
126 + })
127 + .submit(inputValues, errorCode);
128 + }
129 +
130 +</script>
...\ No newline at end of file ...\ No newline at end of file
1 +/**
2 + * Const Values
3 + */
4 +
5 +var ErrorCodeMessages = {
6 + undefined: '등록되지 않은 오류가 발생했습니다. 다시 시도해주세요.',
7 + 'error-00': '셀을 다시 선택해주세요.',
8 + 'error-01': '한번에 강의실만 선택해주세요.',
9 + 'error-02': '상단 혹은 좌측의 Header 선택에서 제외해주세요.',
10 + 'error-03': '해당 강의실의 수용인원이 초과되었습니다.',
11 + 'error-04': '선택한 시간 범위가 잘못되었습니다.',
12 + 'error-05': '이미 예약된 시간입니다.'
13 +};
14 +
15 +
16 +function onOpen(e) {
17 + SpreadsheetApp.getUi()
18 + .createAddonMenu()
19 + .addItem('View records', 'showSidebar')
20 + .addToUi();
21 + showSidebar();
22 +}
23 +
24 +/**
25 + * Runs when the add-on is installed; calls onOpen() to ensure menu creation and
26 + * any other initializion work is done immediately.
27 + *
28 + * @param {Object} e The event parameter for a simple onInstall trigger.
29 + */
30 +function onInstall(e) {
31 + onOpen(e);
32 +}
33 +
34 +/**
35 + * Opens a sidebar. The sidebar structure is described in the Sidebar.html
36 + * project file.
37 + */
38 +function showSidebar() {
39 + var ui = HtmlService.createTemplateFromFile('Sidebar')
40 + .evaluate()
41 + .setSandboxMode(HtmlService.SandboxMode.IFRAME)
42 + .setTitle('KHU Classroom Lender');
43 + SpreadsheetApp.getUi().showSidebar(ui);
44 +}
45 +
46 +function getRange() {
47 + var sheet = SpreadsheetApp.getActiveSheet();
48 + var range = sheet.getActiveRange();
49 + var values = range.getValues();
50 + var row = range.getRow();
51 + var col = range.getColumn();
52 + var width = range.getWidth();
53 + var height = range.getHeight();
54 + var topHeader = sheet.getRange(1, col).getValue();
55 + var date = sheet.getRange(1, 1).getValue();
56 + return [{values, row, col, width, height}, topHeader, date];
57 +}
58 +
59 +function submit(inputValues, errorCode) {
60 + var ui = SpreadsheetApp.getUi();
61 +
62 + // 에러가 발생했는지 확인
63 + if (errorCode != '') {
64 + // alert 출력
65 + var msg = (errorCode in ErrorCodeMessages) ? ErrorCodeMessages[errorCode] : ErrorCodeMessages[undefined];
66 + ui.alert(msg);
67 + return;
68 + }
69 +
70 + // 변수들이 모두 입력되었는지 확인
71 + if (inputValues.profName === '' ||
72 + inputValues.classCode === '' ||
73 + inputValues.className === '' ||
74 + inputValues.numPeople === '') {
75 + ui.alert('누락된 정보가 있습니다. 모두 입력해주세요.');
76 + }
77 +
78 + // 백엔드에다가 여기 예약한다고 보내기
79 +
80 + // 최종 확인
81 + var msg = '예약 대상이 [' + inputValues.classRoom + ' / ' + inputValues.time + '] 맞습니까?';
82 + var response = ui.alert('예약 확인', msg, ui.ButtonSet.YES_NO);
83 + if (response != ui.Button.YES) {
84 + ui.alert('예약이 취소되었습니다.');
85 + return;
86 + }
87 +
88 + // 셀 병합
89 + var sheet = SpreadsheetApp.getActiveSheet();
90 + var range = getRange()[0];
91 + var sheetRange = sheet.getRange(range.row, range.col, range.height, range.width)
92 + sheetRange.merge();
93 +
94 + // 셀에 값 주기
95 + var cellValue = inputValues.className + '\n' + inputValues.profName;
96 + sheetRange.setValue(cellValue);
97 +
98 + ui.alert('예약됐다 치자.');
99 + return;
100 +}
...\ No newline at end of file ...\ No newline at end of file