From 60fd93e12ce424b45d27326f82b8e2414867d5aa Mon Sep 17 00:00:00 2001 From: leebj Date: Tue, 4 Jun 2024 15:22:59 +0900 Subject: [PATCH] =?UTF-8?q?1.xit-web-res=20=EC=B6=94=EA=B0=80=202.js?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EA=B2=BD=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../WEB-INF/jsp/fims/user/user-info.jsp | 2 +- src/main/webapp/WEB-INF/jsp/include/tail.jsp | 10 +- src/main/webapp/resources/html/pdf.html | 2 +- .../webapp/resources/js/base/authority.js | 188 --- src/main/webapp/resources/js/base/code.js | 79 - src/main/webapp/resources/js/base/dataset.js | 1447 ----------------- .../webapp/resources/js/base/menu-support.js | 292 ---- src/main/webapp/resources/js/base/menu.js | 77 - 9 files changed, 8 insertions(+), 2091 deletions(-) delete mode 100644 src/main/webapp/resources/js/base/authority.js delete mode 100644 src/main/webapp/resources/js/base/code.js delete mode 100644 src/main/webapp/resources/js/base/dataset.js delete mode 100644 src/main/webapp/resources/js/base/menu-support.js delete mode 100644 src/main/webapp/resources/js/base/menu.js diff --git a/pom.xml b/pom.xml index 048634e9..5cb68819 100644 --- a/pom.xml +++ b/pom.xml @@ -69,7 +69,7 @@ cokr.xit.base - xit-web-ui + xit-web-res 23.04.01-SNAPSHOT diff --git a/src/main/webapp/WEB-INF/jsp/fims/user/user-info.jsp b/src/main/webapp/WEB-INF/jsp/fims/user/user-info.jsp index 13711ecf..36c2704b 100644 --- a/src/main/webapp/WEB-INF/jsp/fims/user/user-info.jsp +++ b/src/main/webapp/WEB-INF/jsp/fims/user/user-info.jsp @@ -221,7 +221,7 @@ - + diff --git a/src/main/webapp/WEB-INF/jsp/include/tail.jsp b/src/main/webapp/WEB-INF/jsp/include/tail.jsp index 56255f6b..e8e34e3e 100644 --- a/src/main/webapp/WEB-INF/jsp/include/tail.jsp +++ b/src/main/webapp/WEB-INF/jsp/include/tail.jsp @@ -19,15 +19,15 @@ - + - + - - + + - + diff --git a/src/main/webapp/resources/html/pdf.html b/src/main/webapp/resources/html/pdf.html index f6534d45..11679c73 100644 --- a/src/main/webapp/resources/html/pdf.html +++ b/src/main/webapp/resources/html/pdf.html @@ -40,7 +40,7 @@ - + diff --git a/src/main/webapp/resources/js/base/authority.js b/src/main/webapp/resources/js/base/authority.js deleted file mode 100644 index a399a09b..00000000 --- a/src/main/webapp/resources/js/base/authority.js +++ /dev/null @@ -1,188 +0,0 @@ -class AuthorityControl { - constructor() { - this.authorities = new DatasetControl({ - prefix:"authority", - prefixName:"권한", - keymapper:info => info.AUTH_ID, - dataGetter:obj => obj.authorityList, - formats: { - REG_DT:datetimeFormat - } - }); - - this.authorities.isBuiltIn = (info) => { - let current = info || this.authorities.getCurrent(); - return current && current.AUTH_TYPE < 2; - }; - - this.authorities.isImplicit = (info) => { - let current = info || this.authorities.getCurrent(); - return current && current.AUTH_TYPE === 1; - }; - - this.authorities.isAdmin = (info) => { - let current = info || this.authorities.getCurrent(); - return current && current.AUTH_TYPE === 0; - }; - - this.users = new DatasetControl({ - prefix:"user", - prefixName:"사용자", - keymapper:info => info.AUTH_ID + "-" + info.USER_ID, - dataGetter:obj => obj.userList, - formats: { - REG_DT:datetimeFormat - }, - urls:{ - load:wctx.url("/authority/user/list.do") - } - }); - - this.actions = new DatasetControl({ - prefix:"action", - prefixName:"기능 그룹", - keymapper:info => info.AUTH_ID + "-" + info.GRP_ID, - dataGetter:obj => obj.actionList, - formats: { - REG_DT:datetimeFormat - }, - urls:{ - load:wctx.url("/authority/action/list.do") - } - }); - - this.linkedList = "users"; - - this.authorities.onDatasetChange = obj => this.onAuthorityListChange(obj); - this.authorities.onCurrentChange = item => { - this.onCurrentAuthorityChange(item); - let info = item ? item.data : null; - this.getLinkedList(this.linkedList, info); - }; - this.authorities.onSelectionChange = selected => this.onAuthoritySelect(selected); - - this.users.onDatasetChange = obj => this.onUserListChange(obj); - this.users.onCurrentChange = item => this.onCurrentUserChange(item); - this.users.onSelectionChange = selected => this.onUserSelect(selected); - - this.actions.onDatasetChange = obj => this.onActionListChange(obj); - this.actions.onCurrentChange = item => this.onCurrentActionChange(item); - this.actions.onSelectionChange = selected => this.onActionSelect(selected); - } - - getLinkedList(linked, info) { - if (!info) - info = this.authorities.getCurrent(); - switch (this.linkedList = linked) { - case "users": - if (info && !this.authorities.isImplicit(info)) { - if (this.users.query.authIDs == info.AUTH_ID) return; - this.users.query.authIDs = info.AUTH_ID; - this.users.load(); - } else { - this.users.query.authIDs = info.AUTH_ID; - this.users.dataset.clear(); - } - break; - case "actions": - if (info && !this.authorities.isAdmin(info)) { - if (this.actions.query.authIDs == info.AUTH_ID) return; - this.actions.query.authIDs = info.AUTH_ID; - this.actions.load(); - } else { - this.actions.query.authIDs = info.AUTH_ID; - this.actions.dataset.clear(); - } - break; - default: break; - } - } - - onAuthorityListChange(obj) {} - - onCurrentAuthorityChange(item) {} - - onAuthoritySelect(selected) {} - - removeAuthorities() { - let authIDs = this.authorities.dataset.getKeys("selected"); - this.authorities.remove({authIDs:authIDs.join(",")}); - } - - onUserListChange(obj) {} - - onCurrentUserChange(item) {} - - onUserSelect(selected) {} - - onActionListChange(obj) {} - - onCurrentActionChange(item) {} - - onActionSelect(selected) {} - - async addUsers() { - let userIDs = await new UserControl().selectUser(true); - let authID = this.authorities.dataset.getCurrent().AUTH_ID; - json.post({ - url:wctx.url("/authority/user/add.do"), - data:{ - authID:authID, - userIDs:userIDs.join(",") - }, - success:resp => { - if (resp.saved) - this.users._load(); - } - }); - } - - removeUsers() { - let selected = this.users.dataset.getDataset("selected").map(info => info.USER_ID); - let authID = this.authorities.dataset.getCurrent().AUTH_ID; - json.post({ - url:wctx.url("/authority/user/remove.do"), - data:{ - authID:authID, - userIDs:selected.join(",") - }, - success:resp => { - if (resp.saved) - this.users._load(); - } - }); - } - - async addActions() { - let actions = await new ActionGroupControl(false).selectActionGroup(true); - let authID = this.authorities.dataset.getCurrent().AUTH_ID; - - json.post({ - url:wctx.url("/authority/action/add.do"), - data:{ - authID:authID, - groupIDs:actions.join(",") - }, - success:resp => { - if (resp.saved) - this.actions._load(); - } - }); - } - - removeActions() { - let selected = this.actions.dataset.getDataset("selected").map(info => info.GRP_ID); - let authID = this.authorities.dataset.getCurrent().AUTH_ID; - json.post({ - url:wctx.url("/authority/action/remove.do"), - data:{ - authID:authID, - groupIDs:selected.join(",") - }, - success:resp => { - if (resp.saved) - this.actions._load(); - } - }); - } -} diff --git a/src/main/webapp/resources/js/base/code.js b/src/main/webapp/resources/js/base/code.js deleted file mode 100644 index b4f45c05..00000000 --- a/src/main/webapp/resources/js/base/code.js +++ /dev/null @@ -1,79 +0,0 @@ -class CodeControl { - constructor() { - this.groups = new DatasetControl({ - prefix:"group", - prefixName:"코드그룹", - keymapper:info => info.GRP_ID, - dataGetter:obj => obj.groupList, - formats: { - REG_DT:datetimeFormat - }, - urls:{ - load:wctx.url("/code/group/list.do"), - getInfo:wctx.url("/code/group/info.do"), - create:wctx.url("/code/group/create.do"), - update:wctx.url("/code/group/update.do"), - remove:wctx.url("/code/group/remove.do") - } - }); - - this.codes = new DatasetControl({ - prefix:"code", - prefixName:"코드", - keymapper:info => info.CODE, - dataGetter:obj => obj.codeList, - formats: { - REG_DT:datetimeFormat - } - }); - this.codes.remove = (params) => { - let selected = this.codes.dataset.getKeys("selected"); - if (selected.length < 1) return; - - if (!params) { - params = {}; - } - params.groupID = this.groups.dataset.getCurrent()["GRP_ID"]; - params.codes = selected.join(","); - - ajax.post({ - url:this.codes.urls.remove, - data:params, - success:resp => this.codes.onRemove(selected, resp) - }); - }; - - this.groups.onDatasetChange = obj => this.onGroupListChange(obj); - this.groups.onCurrentChange = item => { - this.onCurrentGroupChange(item); - - let info = item ? item.data : null; - if (info) { - this.codes.query.groupIDs = info.GRP_ID; - this.codes.load(); - } else - this.codes.dataset.clear(); - }; - this.groups.onSelectionChange = selected => this.onGroupSelect(selected); - - this.codes.onDatasetChange = obj => this.onCodeListChange(obj); - this.codes.onCurrentChange = item => this.onCurrentCodeChange(item); - this.codes.onSelectionChange = selected => this.onCodeSelect(selected); - } - - onGroupListChange(obj) {} - - onCurrentGroupChange(item) {} - - onGroupSelect(selected) {} - - newCode() { - this.codes.newInfo({GRP_ID:this.groups.getCurrent().GRP_ID}) - } - - onCodeListChange(obj) {} - - onCurrentCodeChange(item) {} - - onCodeSelect(selected) {} -} \ No newline at end of file diff --git a/src/main/webapp/resources/js/base/dataset.js b/src/main/webapp/resources/js/base/dataset.js deleted file mode 100644 index c00478b4..00000000 --- a/src/main/webapp/resources/js/base/dataset.js +++ /dev/null @@ -1,1447 +0,0 @@ -/* Copyright (c) 2020 Emjay Khan. All rights reserved. */ - -/**@file Classes and objects to help control user data in HTML pages - */ - -function lpad(v) { - return v < 10 ? "0" + v : v; -} - -/** value format for numbers */ -const numberFormat = { - /**Parses the value for a number - * @param {(string|number)} value value to parse - * @returns {number} number parsed from the value - */ - parse(value) { - if (!value) return 0; - - switch (typeof(value)) { - case "number": return value; - case "string": - let num = Number(value.replace(/[\s,]/g, "")); - if (!isNaN(num)) - return num; - default: return ValueFormat.InvalidValue; - } - }, - - /**Formats the value - * @param {number} value value to format - * @returns {string} formatted value - */ - format(value) { - let num = numberFormat.parse(value); - return num != ValueFormat.InvalidValue ? Number(num).toLocaleString() : ValueFormat.InvalidValue; - } -}; - -/** value format for dates */ -const dateFormat = { - /**Formats the value - * @param {number} value value to format - * @returns {string} formatted value - */ - format(value) { - if (isEmpty(value)) return ""; - - let _format = v => { - let date = "number" == typeof v ? new Date(v) : v; - let year = date.getFullYear(), - month = lpad(date.getMonth() + 1), - day = lpad(date.getDate()); - return year + "-" + month + "-" + day; - }; - - switch (value instanceof Date ? "date" : typeof value) { - case "number": - case "date": return _format(value); - case "string": return value.substr(0, 4) + "-" + value.substr(4, 2) + "-" + value.substr(6, 2); - default: return ""; - } - }, - - parse(value) { - return isEmpty(value) ? "" : value.replace(/-/gi, ""); - } -}; - -/** value format for time */ -const timeFormat = { - /**Formats the value - * @param {number} value value to format - * @returns {string} formatted value - */ - format(value) { - let _format = v => { - let date = "number" == typeof v ? new Date(v) : v, - hours = lpad(date.getHours()), - minutes = lpad(date.getMinutes()), - seconds = lpad(date.getSeconds()); - return hours + ":" + minutes + ":" + seconds; - }; - - switch (value instanceof Date ? "date" : typeof value) { - case "number": - case "date": return _format(value); - case "string": - let offset = value.length - 6; - return value.substr(0 + offset, 2) + ":" + value.substr(2 + offset, 2) + ":" + value.substr(4 + offset) - default: return ""; - } - }, - - parse(value) { - return isEmpty(value) ? "" : value.replace(/:/gi, ""); - } -} - -/** value format for datetimes */ -const datetimeFormat = { - /**Formats the value - * @param {number} value value to format - * @returns {string} formatted value - */ - format(value) { - switch (value instanceof Date ? "date" : typeof value) { - case "number": - case "date": return dateFormat.format(value) + " " + timeFormat.format(value); - case "string": return dateFormat.format(value) + " " + timeFormat.format(value); - default: return ""; - } - }, - - parse(value) { - return isEmpty(value) ? "" : timeFormat.parse(dateFormat.parse(value)).replace(/ /gi, ""); - } -}; - -/**Manages value formats. - * A value format is an object that has functions - * - * And each value format is associatd with a key as follows. - *
let valueFormats = new ValueFormat({
- *   key0: numberFormat,
- *   key1: dateFormat,
- *   key2: {
- *     format(value) {...},	
- *     parse(value) {...}	
- *   }
- * })
- */ -class ValueFormat { - _formats; - _exprs; - - /**Creates a new ValueFormat. - * @param {object} formats an object whose property names are keys and property values are value formats associated with the keys - */ - constructor(formats) { - this._formats = formats || {}; - this._exprs = {}; - } - - /**Returns a parser associated with the key. - * @param {string} key key associated with a value format - * @returns {function} - * - */ - parser(key) { - let parser = this._formats[key]; - return parser && parser.parse ? parser.parse : ValueFormat.Default.parse; - } - - /**Returns a formatter associated with the key. - * @param {string} key key associated with a value format - * @returns {function} - * - */ - formatter(key) { - let formatter = this._formats[key]; - return formatter && formatter.format ? formatter.format : ValueFormat.Default.format; - } - - regexp(key) { - let expr = this._exprs[key]; - if (!expr) - this._exprs[key] = expr = new RegExp("{" + key + "}", "g"); - return expr; - } -} - -/**Default ValueFormat - */ -ValueFormat.Default = { - parse(value) {return value;}, - format(value) {return ifEmpty(value, "");} -}; -/** Represents an invalid value. */ -ValueFormat.InvalidValue = "^invalid^value^"; - -/**Wraps a user data and traces the manipulation performed on it and consequent status. - */ -class DataItem { - /** user data */ - data; - /** value formatters */ - _formats; - /** whether the user data is selected or not */ - selected; - /** state of the user data */ - state; - - /**Creates a new DataItem. - * @param {any} data user data - * @param {object} formats value formatters of the user data's property - */ - constructor(data, formats) { - this.data = data; - this._formats = formats; - this.selected = false; - this.state = null; - } - - /**selects or unselects the user data. - * @param {boolean} select - * - * @returns {boolean} whether selection status is changed - * - * @example - * - */ - select(select) { - let arg = ifEmpty(select, true), - dirty = this.selected != arg; - this.selected = arg; - return dirty; - } - - /**Returns whether the user data is either created, modified, or removed. - * @returns {boolean} - * - */ - get dirty() { - return ["added", "modified", "removed"].includes(this.state); - } - - /**Returns whether the user data is unreachable. - * @returns {boolean} - * - */ - get unreachable() { - return ["removed", "ignore"].includes(this.state); - } - - /**Toggles the selection status. - * @returns {boolean} current selection status - * - */ - toggle() { - return this.selected = !this.selected; - } - - /**Returns the formatted value of the named property of the user data. - * @param {string} property property name - * @returns {any} formatted value of the named property of the user data - */ - getValue(property) { - let value = this.data[property]; - return this._formats.formatter(property)(value); - } - - /**Parses and sets the value to the named property of the user data. - * @param {string} property property name - * @param {any} value value - * @return {any} - * - */ - setValue(property, value) { - let parsed = this._formats.parser(property)(value); - if (ValueFormat.InvalidValue != parsed) - this.data[property] = parsed; - return parsed; - } - - /**Returns a string converted from the template using the property values of the user data. - * In the template, placeholder for the properties of the user data is specified like {property name}. - * @param {string} template template string - * @param {function} formatter function to format a row string with custom property placeholders - * @returns {string} string converted from the template using the property values of the user data - */ - inString(template, formatter) { - let str = template; - if (formatter) { - str = formatter(str, this); - } - for (let p in this.data) { - let regexp = this._formats.regexp(p); - str = str.replace(regexp, this.getValue(p)); - } - return str; - } -} - -/**Manages user data wrapped in {@link DataItem}s, tracing the state after manipulation performed on them. - *

For a Dataset to work properly, it needs a keymapper to identify user data. - * And you specify it in a Dataset's configuration. - *

let dataset = new Dataset({
- *   keymapper: function(info) {return info.keyProperty;},
- *   ...
- * });
- *

- *

To help access values of user data, a Dataset offers methods - *

- * Using value formats configured in the Dataset, the methods return formatted value and sets parsed value. - *
let dataset = new Dataset({
- *   formats: {
- *     numericProperty: {@link numberFormat},
- *     customProperty: {
- *       format(value) {...},
- *       parse(value) {...},
- *     }
- *   },
- *   ...
- * });
- *

- *

Working with user data that a Dataset holds, you change the Dataset's state. - * Depending on the type of change, the Dataset calls back approriate methods. - * By default, the methods log the content of the change. - *

- *

To override the behavior of the callback methods, - * define a function with the same signature as the method to override - * and assign it to the Dataset's method. - *

let myFunc = obj => {...};
- * let dataset = new Dataset({...});
- * dataset.onDatasetChange = myFunc;
- * You can make it simple like this: - *
let dataset = new Dataset({...});
- * dataset.onDatasetChange = obj => {};
- *

- *

Or you specify an overriding function in the configuration used to create a Dataset. - *

let dataset = new Dataset({
- *     ...
- *     onDatasetChange:obj => {...}
- * });
- *

- */ -class Dataset { - _items; - _byKeys; - _current; - - /**Dataset configuration - */ - conf; - _formats; - - /**Creates a new Dataset with a configuration. - * The configuration is an object with which you specify - * - * @param conf {object} configuration - */ - constructor(conf) { - this._items = []; - this._byKeys = {}; - this._current = null; - - this.conf = notEmpty(conf, "conf is required but missing"); - notEmpty(conf.keymapper, "keymapper is required but missing"); - this._formats = new ValueFormat(conf.formats); - - if (!conf.trace) - this.log = () => {}; - - [ "onDatasetChange", - "onCurrentChange", - "onSelectionChange", - "onAppend", - "onModify", - "onReplace", - "onRemove", - "onDirtiesChange" - ].forEach(on => { - let handler = conf[on] - if (handler && "function" == typeof handler) - this[on] = handler; - }); - } - - /**Logs a message to the console. - * @param args arguments to log - */ - log(...args) { - console.log.apply(console, args); - } - - /**Returns the key of a user data. - * @param {any|DataItem} info user data or {@link DataItem dataItem} of a user data - * @returns {string} key of a user data - */ - getKey(info) { - let data = info ? info.data || info : null; - return data ? this.conf.keymapper(data) : null; - } - - /**Returns keys of the Dataset's user data. - * @param {string} status option regarding the Dataset's user data - * - * @returns {array} keys of the Dataset's user data. - * @example - * //Other than "dirty" status, keys of user data are returned in an array. - * let array = dataset.getKeys(); - * array = dataset.getKeys("selected"); - * //With "dirty" status, keys of user data are returned in an object of status-array pairs. - * let dirties = dataset.getKeys("dirty"); - * let added = dirties.added; - * let modified = dirties.modified; - * let removed = dirties.removed; - */ - getKeys(status){ - let dataset = this.getDataset(status); - if ("dirty" != status) - return dataset.map(e => this.getKey(e)); - - let result = {}; - for (let prop in dataset) { - result[prop] = dataset[prop].map(e => this.getKey(e)); - } - return result; - } - - /**Returns user data or dataItem associated with the key. - * @param {string} key key to a user data - * @param {string} option "item" to get the user data in a dataItem. - * @returns {any|DataItem} user data or dataItem associated with the key - * @example - * //To get user data associated with a key - * let data = dataset.getData("key-0"); - * //To get the user data in a dataItem - * let dataItem = dataset.getData("key-0", "item"); - */ - getData(key, option) { - let item = this._byKeys["key-" + key]; - if (!item || item.unreachable) - return null; - return "item" == option ? item : item.data; - } - - /**Sets user data to the Dataset. - * To get user data from an object, the dataGetter configured is called. - * After user data is set, the methods - * - * are called back. - * @param {array|object} obj user data or an object that has user data - * @returns {Dataset} the Dataset - */ - setData(obj) { - let state = this.state; - this._byKeys = {}; - this._current = null; - - obj = obj || {}; - - let data = this._getDataItems(obj); - this._items = data.items; - this._byKeys = data.byKeys; - /* - obj = obj || {}; - let array = Array.isArray(obj) ? obj : this.conf.dataGetter(obj) || []; - if (!Array.isArray(array)) - throw new Error("The data must be an array"); - - this._items = array.map(e => new DataItem(e, this._formats)); - this._items.forEach(item => { - let key = "key-" + this.getKey(item.data); - this._byKeys[key] = item; - }); - */ - this.onDatasetChange(obj); - this.setState(!Array.isArray(obj) ? obj.state : state); - this.onDirtiesChange(this.dirty); - - return this; - } - - _getDataItems(obj) { - obj = obj || {}; - let array = Array.isArray(obj) ? obj : this.conf.dataGetter(obj) || []; - if (!Array.isArray(array)) - throw new Error("The data must be an array"); - - let _items = array.map(e => new DataItem(e, this._formats)), - _byKeys = {}; - _items.forEach(item => { - let key = "key-" + this.getKey(item.data); - _byKeys[key] = item; - }); - - return { - items: _items, - byKeys: _byKeys - }; - } - - /**Adds user data to the Dataset. - * To get user data from an object, the dataGetter configured is called. - * After user data is set, the methods - * - * are called back. - * @param {array|object} obj user data or an object that has user data - * @returns {Dataset} the Dataset - */ - addData(obj) { - if (this.empty) - return this.setData(obj); - - let state = this.state; - let data = this._getDataItems(obj); - this._items = this._items.concat(data.items); - this._byKeys = { - ...this._byKeys, - ...data.byKeys - }; - - obj = obj || {} - - this.onDatasetChange(obj); - this.setState(!Array.isArray(obj) ? obj.state : state); - this.onDirtiesChange(this.dirty); - - return this; - - } - - /**Clears the Dataset's user data. - * @returns {Dataset} the Dataset - */ - clear() { - this.setData(null); - return this; - } - - /**Returns the length or count of the Dataset's user data. - * @returns {number} length or count of the Dataset's user data - */ - get length(){return this.getDataset("item").length;}; - - /**Returns whether the Dataset has no user data or not. - * @returns {boolean} - * - */ - get empty(){ - return this.length < 1; - } - - /**Returns the current user data or dataItem. - * @param {string} option "item" to get the current dataItem - * @returns {any|DataItem} current user data or dataItem - * @example - * //To get the current user data - * let current = dataset.getCurrent(); - * //To get the current user data in a dataItem - * let current = dataset.getCurrent("item"); - */ - getCurrent(option){ - let current = this._current; - if (!current || current.unreachable) - return null; - return "item" == option ? current : current.data; - } - - /**Sets the user data as current that is associated with the key. - * @param {string} key key to a user data - * After the data is set, the method - * - * is called back. - */ - setCurrent(key, fire) { - let current = this.getCurrent("item"), - item = this.getData(key, "item") || new DataItem({}, this._formats), - diff = current !== item; - - this._current = item; - - if (diff || fire) - this.onCurrentChange(item); - } - - /**Returns the Dataset's current state in an object. - * The object has the properties as follows. - * - * @returns {object} Dataset's current state - */ - get state() { - let empty = this.empty, - self = this; - return { - currentKey:!empty ? self.getKey(self.getCurrent()) : null, - selectedKeys:!empty ? self.getKeys("selected") : [] - }; - } - - /**Sets the state to the Dataset. - * After the state is set, the methods - * - * are called back. - * @param {object} state state of the Dataset - * The state is an object of the following properties. - * - * @returns {Dataset} the Dataset - */ - setState(state) { - if (this.empty) { - this.onCurrentChange(null); - this.onSelectionChange([]); - this.onDirtiesChange(false); - } else { - state = state || this.state; - let current = this.getData(state.currentKey) || this.getDataset()[0], - currentKey = this.getKey(current); - this.setCurrent(currentKey, true); - this.select(state.selectedKeys || [], true, true); - } - return this; - } - - /**Returns an array of user data or dataItems. - * @param {string} status - * - * @param {string} option - * - * @returns {array|object} - * - * @example - * //To get all user data - * let dataList = dataset.getDataset(); - * //To get all user data in dataItems - * let dataItems = dataset.getDataset("item"); - * //To get selected user data - * let dataList = dataset.getDataset("selected"); - * //To get selected user data in dataItems - * let dataItems = dataset.getDataset("selected", "item"); - * //To get user data that are either added, modified, or removed - * let dataList = dataset.getDataset("added"); - * dataList = dataset.getDataset("modified"); - * dataList = dataset.getDataset("removed"); - * //To get user data in dataItems that are either added, modified, or removed. - * let dataItems = dataset.getDataset("added", "item"); - * dataItems = dataset.getDataset("modified", "item"); - * dataItems = dataset.getDataset("removed", "item"); - * //To get dirty user data - * let dirties = dataset.getDataset("dirty"); - * let added = dirties.added; - * let modified = dirties.modified; - * let removed = dirties.removed; - * //To get dirty user data in dataItems - * let dirties = dataset.getDataset("dirty", "item"); - * let added = dirties.added; - * let modified = dirties.modified; - * let removed = dirties.removed; - */ - getDataset(status, option) { - let items = this._items, - result = null; - if ("item" == status) - option = "item"; - switch (status) { - case "selected" : result = items.filter(item => item.selected && !item.unreachable); break; - case "added": - case "modified": - case "removed": result = items.filter(item => status == item.state); break; - case "dirty": - result = {}; - items.filter(item => item.dirty) - .forEach(item => { - let state = item.state, - array = result[state]; - if (!array) - result[state] = array = []; - array.push(item); - }); - break; - case "item": - default: result = items.filter(item => !item.unreachable); break; - } - if ("item" == option) - return result; - - let getData = item => item.data; - if ("dirty" != status) - return "item" == option ? result : result.map(e => getData(e)); - - for (let prop in result) { - result[prop] = result[prop].map(e => getData(e)); - } - return result; - } - - /**Returns whether the Dataset is dirty. - * A Dataset is dirty if it has user data that is either added, modified, or removed. - * @returns {boolean} whether the Dataset is dirty - * - */ - get dirty() { - return this._items - .filter(item => item.dirty) - .length > 0; - } - - /**Selects or unselects user data depending on the arguments. - * After the selection change, the method - * - * is called. - * @example - * //To select a user data - * dataset.select("key0") or dataset.select("key0", true) - * //To select multiple user data - * dataset.select(["key0", "key1"]) or dataset.select(["key0", "key1"], true) - * //To select all user data - * dataset.select() or dataset.select(true) - * //To unselect a user data - * dataset.select("key0", false) - * //To unselect multiple user data - * dataset.select(["key0", "key1"], false) - * //To unselect all user data - * dataset.select(false) - */ - select(...args) { - let arg0 = ifEmpty(args[0], true), - arg1 = ifEmpty(args[1], true), - dirty = false, - fire = false; - if ("boolean" == typeof arg0) { - for (let i = 0, length = this.length; i < length; ++i) { - dirty = this._items[i].select(arg0) || dirty; - } - fire = args[1]; - } else { - let keys = Array.isArray(arg0) ? arg0 : [arg0]; - for (let i = 0; i < keys.length; ++i) { - let item = this.getData(keys[i], "item"); - if (item) - dirty = item.select(arg1) || dirty; - } - fire = args[2]; - } - if (dirty || fire) { - this.onSelectionChange(this.getDataset("selected")); - } - return dirty; - } - - /**Toggles selection of the user data associated with the key. - * After the selection change, the method - * - * is called. - * @param {string} key key associated with user data - * @returns {boolean} selection status of the user data - * - */ - toggle(key) { - let item = this.getData(key, "item"), - status = item ? item.toggle() : false; - this.onSelectionChange(this.getDataset("selected")); - return status; - } - - /**appends user data to the Dataset. - * After the user data is appended, the methods - * - * are called. - * @param data {object|array} user data or array of user data - * @returns the Dataset - */ - append(data) { - if (!data) return this; - - let notDirty = !this.dirty, - array = Array.isArray(data) ? data : [data]; - array.forEach(e => { - let item = new DataItem(e, this._formats); - this._items.push(item); - - let key = this.getKey(e); - this._byKeys["key-" + key] = item; - item.state = "added"; - }); - - let state = this.state; - this.onAppend(array); - state.currentKey = this.getKey(array[array.length - 1]); - this.setState(state); - - if (notDirty) - this.onDirtiesChange(true); - - return this; - }; - - /**Modifies user data associated with the key using the modifier. - * After user data modification, the methods - * - * are called. - * @param {string} key key to a Dataset's user data - * @param {function} modifier function that modifies the user data. - * The function must have a sigunature that accepts a DataItem. - * If the modification fails, it must return ValueFormat.InvalidValue. - * @returns the Dataset - * @example - * let v = ...; - * let modifier = (dataItem) => { - * if (v !== ...) - * return ValueFormat.InvalidValue; - * let data = dataItem.data; - * data.prop = v; - * }; - * ... - * dataset.modify("key0", modifier); - */ - modify(key, modifier) { - if (!modifier) return this; - - let item = this.getData(key, "item"); - if (!item) - return log("Item not found with " + key); - - let notDirty = !this.dirty, - data = item.data, - prev = Object.assign({}, data), - modifiedProps = (prev, data) => { - let changed = []; - for (let prop in data) { - let oldVal = prev[prop], - newVal = data[prop]; - if (oldVal != newVal) - changed.push(prop); - } - return changed; - }; - - let current = data == this.getCurrent(), - revert = modifier(item) == ValueFormat.InvalidValue, - changed = modifiedProps(prev, data); - - if (changed.length > 0) { - if (!item.state) - item.state = "modified"; - this.onModify(changed, item, current); - if (notDirty) - this.onDirtiesChange(true); - } else if (revert) { - this.onModify(Object.getOwnPropertyNames(data), item, current); - } - - return this; - } - - /**Replaces the Dataset's user data with the replacement. - * After replacement, the methods - * - * are called. - * @param {object|array} replacement - * replacement is an object or an array of objects of the following properties. - * - * @returns {Dataset} the Dataset - * @example - * //To replace old-keyed user data with new-keyed user data. - * dataset.replace({key:"old-key", data:{id:"new-key", ...}}); - * //or - * dataset.replace([ - * {key:"old-key0", data:{id:"new-key0", ...}}, - * {key:"old-key1", data:{id:"new-key1", ...}}, - * ]); - * //To replace user data with equal-keyed user data - * dataset.replace({data:{id:"key0", ...}}); - * //or - * dataset.replace([ - * {data:{id:"key0", ...}}, - * {data:{id:"key1", ...}}, - * ]); - */ - replace(replacement) { - if (isEmpty(replacement)) return this; - - let before = this.dirty, - replacements = Array.isArray(replacement) ? replacement : [replacement], - replacing = []; - replacements.forEach(obj => { - let data = obj.data; - if (!data) return; - - let key = obj.key || this.getKey(data); - if (!key) return; - - let oldItem = this.getData(key, "item"), - newItem = new DataItem(data, this._formats), - pos = oldItem ? this._items.indexOf(oldItem) : -1; - - newItem.selected = oldItem && oldItem.selected; - if (pos > -1) - this._items[pos] = newItem; - else - this._items.push(newItem); - - delete this._byKeys["key-" + key]; - this._byKeys["key-" + this.getKey(data)] = newItem; - - if (this._current == oldItem) - this._current = newItem; - - replacing.push(newItem); - }); - this.onReplace(replacing); - let after = this.dirty; - if (before != after) - this.onDirtiesChange(after); - - return this; - } - - /**Removes user data associated with the key. - * After user data removal, the methods - * - * are called. - * @param {string|array} key key or keys to user data - * @returns {Dataset} the Dataset - * @example - * dataset.remove("key0"); - * dataset.remove(["key0", "key1"]); - */ - remove(key) { - if (!key || this.empty) return this; - - let before = this.dirty, - keys = Array.isArray(key) ? key : [key], - removed = this._items.filter(item => { - let k = this.getKey(item.data), - remove = keys.includes(k); - if (remove) { - item.state = "added" == item.state ? "ignore" : "removed"; - } - return remove; - }), - currentPos = this._items.indexOf(this._current), - state = this.state; - - if (currentPos > -1) { - let newKey = null; - for (let i = currentPos, length = this._items.length; i < length; ++i) { - let item = this._items[i]; - if (item.unreachable) continue; - - newKey = this.getKey(item); - break; - } - if (!newKey) - for (let i = this._items.length - 1; i > 0; --i) { - let item = this._items[i]; - if (item.unreachable) continue; - - newKey = this.getKey(item); - break; - } - state.currentKey = newKey; - } - this.onRemove(removed); - this.setState(state); - let after = this.dirty; - if (before != after) - this.onDirtiesChange(after); - - return this; - } - - /**Erases user data associated with the key. - * After user data removal, the methods - * - * are called. - * Note that unlike {@link Dataset#remove} this method deletes user data completely from the Dataset - * and the erased user data are not traced as dirty user data. - * @param {string|array} key key or keys to user data - * @returns {Dataset} the Dataset - * @example - * dataset.erase("key0"); - * dataset.erase(["key0", "key1"]); - */ - erase(key) { - if (!key || this.empty) return; - - let before = this.dirty, - keys = Array.isArray(key) ? key : [key], - erased = this._items.filter(item => { - let k = this.getKey(item.data), - erase = keys.indexOf(k) > -1; - if (erase) { - delete this._byKeys["key-" + k]; - } - return erase; - }); - - let currentPos = erased.indexOf(this._current) > -1 ? this._items.indexOf(this._current) : -1, - state = this.state; - - if (currentPos > -1) { - let newKey = null; - for (let i = currentPos + 1, length = this._items.length; i < length; ++i) { - let item = this._items[i]; - if (item.unreachable || erased.includes(item)) continue; - - newKey = this.getKey(item); - break; - } - if (!newKey) - for (let i = this._items.length - 1; i > 0; --i) { - let item = this._items[i]; - if (item.unreachable || erased.includes(item)) continue; - - newKey = this.getKey(item); - break; - } - state.currentKey = newKey; - } - this._items = this._items.filter(function(item){return !erased.includes(item);}); - - this.onRemove(erased); - this.setState(state); - let after = this.dirty; - if (before != after) - this.onDirtiesChange(after); - } - - /**Returns an array of strings converted from the template using the property values of the Dataset's user data. - * In the template, placeholder for the properties of the user data is specified like {property name}. - * @param {string} template template string - * @param {function} formatter function to format a row string with custom property placeholders - * @returns {array} array of strings converted from the template using the property values of the user data - */ - inStrings(template, formatter) { - return this.getDataset("item") - .map(item => item.inString(template, formatter)); - } - - /**Returns a property value of user data. - * If a value format is associated with the property, the value is formatted. - * @param args See the example - * @returns {any|string} property value of a user data - * @example - * //To get a property value of user data associated with a key - * let value = dataset.getValue("key0", "property0"); - * //To get a property value of current user data - * let value = dataset.getValue("property0"); - */ - getValue(...args) { - let key = null, - property = null; - switch (args.length) { - case 1: - key = this.getKey(this.getCurrent()); - property = args[0]; - break; - case 2: - key = args[0]; - property = args[1]; - break; - default: return null; - } - - let item = this.getData(key, "item"); - return item ? item.getValue(property) : undefined; - } - - /**Sets a value to a property of user data. - * If a value format is associated with the property, the value is parsed before setting to user data. - * After setting the value, the methods - * - * are called. - * @param args See the example - * @example - * //To set a value to a property of user data associated with a key - * dataset.setValue("key0", "property0", "value0"); - * //To set a value to a property of current user data - * dataset.setValue("property0", "value0"); - */ - setValue(...args) { - let key = null, - property = null, - value = null; - switch (args.length) { - case 2: - key = this.getKey(this.getCurrent()); - property = args[0]; - value = args[1]; - break; - case 3: - key = args[0]; - property = args[1]; - value = args[2]; - break; - default: return this; - } - return this.modify(key, function(item){ - return item.setValue(property, value); - }); - } - - /**Called back when user data are set. - * @param {object|array} obj object that has user data or an array of user data - */ - onDatasetChange(obj) {this.log("Dataset changed", obj);} - - /**Called back when current user data is changed. - * @param {DataItem} currentItem current dataItem - */ - onCurrentChange(currentItem) {this.log("Current changed", currentItem);} - - /**Called back when user data selection changes. - * @param {array} selected array of selected user data - */ - onSelectionChange(selected) {this.log("Selection changed", selected);} - - /**Called back when user data is appended. - * @param {object|array} appended user data or array of user data - */ - onAppend(appended) {this.log("Data appended", appended);} - - /**Called back when user data is modified. - * @param {array} props names of changed properties - * @param {DataItem} modified modified user dataItem - * @param {boolean} current whether current user data is modified - */ - onModify(props, modified, current) {this.log("Data modified", props, modified, current ? "current" : "");} - - /**Called back when user data are replaced. - * @param {array} replacing array of user dataItems replacing the old ones - */ - onReplace(replacing) {this.log("Data replaced", replacing);} - - /**Called back when user data are removed. - * @param {array} removed array of removed dataItems - */ - onRemove(removed) {this.log("Data removed", removed)} - - /**Called back when the Dataset gets dirty or not dirty. - * @param {boolean} dirty - * - */ - onDirtiesChange(dirty){this.log("Dirties change", dirty);} -} - -class DatasetControl { - constructor(conf) { - notEmpty(conf.keymapper, "keymapper"); - this.prefix = conf.prefix; - this.prefixName = conf.prefixName; - this.infoSize = conf.infoSize; - this.appendData = conf.appendData; - - this.query = {}; - - conf.onDatasetChange = obj => this.onDatasetChange(obj), - conf.onCurrentChange = item => this.onCurrentChange(item), - conf.onSelectionChange = selected => this.onSelectionChange(selected), - conf.onAppend = items => this.onAppend(items), - conf.onModify = (props, modified, current) => { - let info = this.dataset.getCurrent("item"); - if (!info || "added" == info.state) - return; - this.onModify(props, modified, current); - } - - this.dataset = new Dataset(conf); - - this.urls = conf.urls || { - load:this.url("/list.do"), - getInfo:this.url("/info.do"), - create:this.url("/create.do"), - update:this.url("/update.do"), - remove:this.url("/remove.do") - }; - } - - prefixed(str) { - return (this.prefix || "") + str; - } - - url(str) { - return wctx.url("/" + this.prefixed(str)); - } - - load(pageNum) { - this.query.pageNum = pageNum; - this._load(); - } - - _load() { - if (!this.query.pageNum) - this.query.pageNum = 1; - - ajax.get({ - url:this.urls.load, - data:this.query, - success:resp => { - if (!this.appendData || this.query.pageNum == 1) - this.setData(resp); - else { - this.addData(resp); - } - } - }); - } - - download(type) { - this.query.download = type || "xls"; - let query = toQuery(this.query); - this.query.download = null; - document.location.href = this.urls.load + "?" + query; - } - - setData(obj) { - this.dataset.setData(obj); - } - - addData(obj) { - this.dataset.addData(obj); - } - - onDatasetChange(obj) { - debug("onDatasetChange", obj); - } - - getCurrent(option) { - return this.dataset.getCurrent(option); - } - - setCurrent(key) { - this.dataset.setCurrent(key); - } - - onCurrentChange(item) { - debug(item); - } - - select(key, selected) { - this.dataset.select(key, selected); - } - - onSelectionChange(selected) { - debug(selected); - } - - getInfo(params) { - let info = this.dataset.getCurrent("item"); - if (this.urls.getInfo) - ajax.get({ - url:this.urls.getInfo, - data:params || {}, - success:resp => { - resp = resp.replace(/infoPrefix/g, this.prefix) - .replace(/prefixName/g, this.prefixName) - dialog.open({ - id:this.prefixed("dialog"), - title: this.prefixName + " 정보", - content:resp, - size:this.infoSize, - init:() => this.setInfo(info) - }); - } - }); - else - this.setInfo(info); - } - - setInfo(info) {} - - newInfo(obj) { - this.dataset.append(obj || {}); - this.getInfo(); - } - - getValue(name) { - return this.dataset.getValue(name); - } - - setValue(name, value) { - this.dataset.setValue(name, value); - } - - onAppend(items) { - debug("on append", items); - } - - onModify(props, modified, current) { - debug("on modify", props, "modified", modified, "current", current); - } - - save(info) { - if (!info) return; - let item = this.getCurrent("item"), - create = "added" == item.state; - - ajax.post({ - url:!create ? this.urls.update : this.urls.create, - data:info, - success:resp => this.onSave(resp) - }); - } - - onSave(resp) { - if (resp.saved) { - dialog.alert("저장됐습니다."); - dialog.close(this.prefixed("dialog")); - this._load(); - } - } - - remove(params) { - let selected = this.dataset.getKeys("selected"); - if (selected.length < 1) return; - - if (!params) { - params = {}; - params[this.prefixed("IDs")] = selected.join(","); - } - - ajax.post({ - url:this.urls.remove, - data:params, - success:resp => this.onRemove(selected, resp) - }); - } - - onRemove(selected, resp) { - if (resp.saved) - this._load(); - } - - bindInputs(obj, selector) { - let inputs = ["input", "select", "textarea"].map(tag => selector + " " + tag).join(","), - setChanged = evt => { - let input = evt.target, - name = input.getAttribute("data-map"), - val = input.value; - this.setValue(name, val); - }; - - document.querySelectorAll(inputs).forEach(input => { - let prop = input.getAttribute("data-map") - || input.name - || input.id; - if (!prop) return; - - input.removeEventListener("change", setChanged); - - let dataItem = obj instanceof DataItem, - value = dataItem ? obj.getValue(prop) : obj[prop], - inputType = (input.type || input.tagName || "").toLowerCase(); - - switch (inputType) { - case "radio": input.checked = value && value == input.value; break; - case "checkbox": input.checked = value && value == input.value; break; - case "select": - for(let option of input.options) { - option.selected = option.value == value; - } - break; - default: input.value = ifEmpty(value, ""); break; - } - input.addEventListener("change", setChanged); - }); - } -} \ No newline at end of file diff --git a/src/main/webapp/resources/js/base/menu-support.js b/src/main/webapp/resources/js/base/menu-support.js deleted file mode 100644 index a41dc26b..00000000 --- a/src/main/webapp/resources/js/base/menu-support.js +++ /dev/null @@ -1,292 +0,0 @@ -/**메뉴의 생성과 선택 시 동작을 지원한다. - */ -class MenuSupport { - /**새 MenuSupport를 생성한다. - * @param selector {string} 메뉴를 담을 컨테이너에 대한 css selector - */ - constructor(conf) { - conf = conf || {}; - this._selector = ifEmpty(conf.selector, "#menus"); - this._containerSelector = ifEmpty(conf.containerSelector, "#layout-menu"); - this._container = document.querySelector(this._containerSelector); - let onclick = conf.onclick || (menu => 'onclick="openMenu(\'{url}\')" '.replace(/{url}/gi, wctx.url(menu.url))); - this._onclick = (menu => menu && menu.url ? onclick(menu) : ""); - - this._horizontal = this._container && this._container.classList.contains('menu-horizontal'); - this._orientation = this._horizontal ? "horizontal" : "vertical"; - this._template = this._orientation + "-menu-template"; - this._menuItem = ''; - this._menuSub = ''; - this._menus = []; - this._init(); - } - - /**메뉴를 생성할 정보를 설정한다. - * @param menus {array} 메뉴 정보 배열
- * 각 메뉴 정보의 레이아웃은 다음과 같다.
- * {"id":메뉴 아이디, "name":"메뉴 이름", "url":"실행 url", "parentID":"상위 메뉴 아이디", "description":"메뉴 설명", "imageConf":"이미지 설정", "displayWindow":"표시 창", "children":[하위 메뉴 배열]} - * @returns MenuSupport - */ - setMenuInfo(menus) { - let setParent = menu => { - let children = menu.children || []; - if (children.length < 1) return; - - children.forEach(child => { - child.parent = menu; - setParent(child); - }); - }; - menus.forEach(menu => setParent(menu)); - this._menus = menus; - - let menuItemTag = menu => { - let tag = this._menuItem - .replace(/{menuID}/gi, menu.id) - .replace(/{menuName}/gi, menu.name) - .replace(/{onclick}/gi, this._onclick(menu)) - .replace(/{title}/gi, (menu.description || "")) - .replace(/{imageConf}/gi, (menu.imageConf || "bx bx-layout")); - let parent = menu.children && menu.children.length > 0; - tag = tag.replace(/{toggle}/gi, !parent ? "" : " menu-toggle"); - if (!parent) - return tag.replace(/{menuSub}/gi, ""); - - let children = menu.children.map(child => menuItemTag(child)).join("\n\t") - return tag.replace(/{menuSub}/gi, this._menuSub.replace(/{children}/gi, children)); - } - let tags = (menus || []).map(menu => menuItemTag(menu)); - document.querySelector(this._selector).innerHTML = tags.join(""); - - return this._init(); - } - - _toggleMenuAwares(collapse) { - document.querySelectorAll(".menu-aware").forEach(menuAware => menuAware.style.width = collapse ? "calc(100% - 5.25rem)" : ""); - } - - _init() { - let menu = new Menu(this._container, { - orientation: this._orientation, - closeChildren: this._horizontal, - showDropdownOnHover: localStorage.getItem('templateCustomizer-' + this._template + '--ShowDropdownOnHover') - ? localStorage.getItem('templateCustomizer-' + this._template + '--ShowDropdownOnHover') === 'true' - : window.templateCustomizer !== undefined - ? window.templateCustomizer.settings.defaultShowDropdownOnHover - : true - }); - window.Helpers.scrollToActive(false); //animate = false - window.Helpers.mainMenu = menu; - - //Sets toggler - document.querySelectorAll('.layout-menu-toggle').forEach(item => { - item.addEventListener('click', event => { - if (event.fired) { - return delete event.fired; - } - event.fired = true; - event.preventDefault(); - window.Helpers.toggleCollapsed(); - if (config.enableMenuLocalStorage && !window.Helpers.isSmallScreen()) { - try { - localStorage.setItem( - 'templateCustomizer-' + this._template + '--LayoutCollapsed', - String(window.Helpers.isCollapsed()) - ); - } catch (e) {} - } - this._toggleMenuAwares(Helpers.isCollapsed()); - }); - }); - // Display menu toggle (layout-menu-toggle) on hover with delay - let delay = (elem, callback) => { - let timeout = null; - elem.onmouseenter = () => { - // Set timeout to be a timer which will invoke callback after 300ms (not for small screen) - timeout = !Helpers.isSmallScreen() ? setTimeout(callback, 300) : setTimeout(callback, 0); - }; - - elem.onmouseleave = () => { - // Clear any timers set to timeout - document.querySelector('.layout-menu-toggle').classList.remove('d-block'); - clearTimeout(timeout); - }; - }; - if (this._container) { - delay(this._container, () => { - // not for small screen - if (!Helpers.isSmallScreen()) { - document.querySelector('.layout-menu-toggle').classList.add('d-block'); - } - }); - } - // Detect swipe gesture on the target element and call swipe In - window.Helpers.swipeIn('.drag-target', function (e) { - window.Helpers.setCollapsed(false); - }); - // Detect swipe gesture on the target element and call swipe Out - window.Helpers.swipeOut(this._containerSelector, function (e) { - if (window.Helpers.isSmallScreen()) window.Helpers.setCollapsed(true); - }); - // Display in main menu when menu scrolls - let menuInnerContainer = document.getElementsByClassName('menu-inner'), - menuInnerShadow = document.getElementsByClassName('menu-inner-shadow')[0]; - if (menuInnerContainer.length > 0 && menuInnerShadow) { - menuInnerContainer[0].addEventListener('ps-scroll-y', function () { - if (this.querySelector('.ps__thumb-y').offsetTop) { - menuInnerShadow.style.display = 'block'; - } else { - menuInnerShadow.style.display = 'none'; - } - }); - } - - return this; - } - - open(url) { - top.document.location.href = url; - } - - /**지정한 url의 메뉴를 활성화 한다. - * @param url {string} 메뉴 url - * @returns MenuSupport - */ - setActive(url) { - let menu = this.getMenu(url); - if (!menu) return this; - - document - .querySelectorAll(this._selector + " li") - .forEach(li => li.classList.remove("active", "open")); - - let a = document.querySelector(this._selector + " li[data-key=\"" + menu.id + "\"]"); - if (!a) return this; - - let activate = (e, open) => { - e.classList.add("active"); - - let p = e.parentNode; - let tag = (p != this._container ? p : null) ? p.tagName : ""; - if (!tag) return; - - if ("li" == tag.toLowerCase()) { - p.classList.add("active"); - if (open) - p.classList.add("open"); - } - activate(p, true); - }; - - activate(a); - - return this; - } - - /**지정하는 url의 메뉴 정보를 반환한다. - * @param url {string} 메뉴 url - * @returns 지정하는 url의 메뉴 정보 - */ - getMenu(url) { - let find = menus => { - for (let i = 0; i < menus.length; ++i) { - let menu = menus[i]; - if (url == menu.url) - return menu; - let found = find(menu.children || []); - if (found) - return found; - } - return null; - }; - return find(this._menus); - } - - breadcrumb(url, separator = " / ") { - let menu = this.getMenu(url); - if (!menu) - return ""; - - let getName = menu => { - let name = menu.name; - let parent = !menu.parent ? "" : getName(menu.parent); - return parent ? parent + separator + name : name; - } - - return getName(menu); - } -} - -class TabControl extends Dataset { - constructor(conf) { - if (!conf) - conf = {}; - conf.keymapper = info => { - if (!info.index) { - info.index = "ndx-" + new Date().getTime(); - } - return info.index; - }; - conf.dataGetter = obj => null; - super(conf); - this.sticky = conf.sticky || {}; - this.maxCount = conf.maxCount || 8; - this.getMenu = conf.getMenu || ((url) => {throw "getMenu(url) missing"}); - - } - - getTab(by) { - if (by.startsWith("ndx-")) - return this.getData(by, "item"); - - if (by != this.sticky.url) { - let found = this._items.filter(item => item.data.url == by), - empty = !found || found.length < 1; - if (empty) - return null; - - found = found[0]; - return !found.unreachable ? found : null; - } else { - let found = this._items.filter(item => item.data.url == this.sticky.url); - if (!found || found.length < 1) { - this.addData([this.sticky]); - } - } - } - - open(url) { - if (!url - || url.startsWith("javascript:void") - || url == this.sticky.url) - return; - - let tab = this.getTab(url); - if (tab) - return this.setCurrent(tab.data.index); - - ajax.get({ - url: wctx.url(url), - success: resp => { - let menu = this.getMenu(url); - if (!menu) - throw "Menu not found for " + url; - - if (this.length == this.maxCount) { - let index = isEmpty(this.sticky) ? 0 : 1, - first = this._items[index]; - this.close(first.data.url) - } - - menu.content = resp; - this.addData([menu]); - this.open(url); - } - }); - } - - close(url) { - let tab = this.getTab(url); - this.erase(tab.data.index); - } -} \ No newline at end of file diff --git a/src/main/webapp/resources/js/base/menu.js b/src/main/webapp/resources/js/base/menu.js deleted file mode 100644 index 13b9b957..00000000 --- a/src/main/webapp/resources/js/base/menu.js +++ /dev/null @@ -1,77 +0,0 @@ -class MenuControl extends DatasetControl { - constructor() { - super({ - keymapper: info => info ? info.id : "", - prefix:"menu", - prefixName:"메뉴" - }); - - this.urls.load = this.url("/tree.do"); - delete this.urls.getInfo; - this.menus = []; - } - - setData(obj) { - let list = []; - let asList = array => { - if (!array || array.length < 1) return; - - for (var i = 0; i < array.length; ++i) { - let menu = array[i]; - list.push(menu); - asList(menu.children); - } - }; - asList(this.menus = Array.isArray(obj) ? obj : obj.menus); - super.setData(list); - } - - move(parentID, menuID) { - json.post({ - url:wctx.url("/menu/move.do"), - data:{ - parentID:parentID, - menuIDs:menuID - }, - success:resp => { - this._load(); - this.onMenusChanged(); - } - }); - } - - reorder(menuIDs) { - json.post({ - url:wctx.url("/menu/reorder.do"), - data:{ - menuIDs:Array.isArray(menuIDs) ? menuIDs.join(",") : menuIDs - }, - success:resp => { - this._load(); - this.onMenusChanged(); - } - }); - } - - onSave(resp) { - super.onSave(resp); - this.onMenusChanged(); - } - - onRemove(selected, resp) { - super.onRemove(selected, resp); - this.onMenusChanged(); - } - - onMenusChanged() {} - - async getUserMenus() { - return new Promise((resolve, reject) => { - json.get({ - url:this.url("/userMenus.do"), - data:{}, - success:resp => resolve(resp.userMenus) - }); - }); - } -} \ No newline at end of file