diff --git a/.gitignore b/.gitignore index a4a6e37..85a5640 100644 --- a/.gitignore +++ b/.gitignore @@ -143,6 +143,7 @@ false *copy.py *.sh data/ +tmp/ lib/support/site/tving.py lib/support/site/wavve.py diff --git a/lib/framework/init_main.py b/lib/framework/init_main.py index c1c8dc8..67a9551 100644 --- a/lib/framework/init_main.py +++ b/lib/framework/init_main.py @@ -104,8 +104,8 @@ class Framework: # https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/config/#flask_sqlalchemy.config.SQLALCHEMY_BINDS # 어떤 편법도 불가. db를 사용하지 않아도 파일이 생김. db_path = os.path.join(self.config['path_data'], 'db', 'system.db') - self.app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{db_path}' # 3.0에서 필수 - self.app.config['SQLALCHEMY_BINDS'] = {'system':f'sqlite:///{db_path}'} + self.app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{db_path}?check_same_thread=False' # 3.0에서 필수 + self.app.config['SQLALCHEMY_BINDS'] = {'system':f'sqlite:///{db_path}?check_same_thread=False'} self.app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False _ = os.path.join(self.config['path_data'], 'plugins') @@ -124,7 +124,7 @@ class Framework: for package_name in plugins: db_path = os.path.join(self.config['path_data'], 'db', f'{package_name}.db') - self.app.config['SQLALCHEMY_BINDS'][package_name] = f'sqlite:///{db_path}' + self.app.config['SQLALCHEMY_BINDS'][package_name] = f'sqlite:///{db_path}?check_same_thread=False' self.db = SQLAlchemy(self.app, session_options={"autoflush": False, "expire_on_commit": False}) #with self.app.app_context(): # self.db.session.expunge_all() diff --git a/lib/framework/static/js/ff_global1.js b/lib/framework/static/js/ff_global1.js index ae3cca9..aee97ec 100644 --- a/lib/framework/static/js/ff_global1.js +++ b/lib/framework/static/js/ff_global1.js @@ -130,6 +130,175 @@ $("body").on('click', '#globalCliboardBtn', function(e) { }); +// 사용 on / off +$("body").on('change', '#globalSchedulerSwitchBtn', function(e) { + e.preventDefault(); + var ret = $(this).prop('checked'); + $.ajax({ + url: '/'+PACKAGE_NAME+'/ajax/' + MODULE_NAME + '/scheduler', + type: "POST", + cache: false, + data: {scheduler : ret}, + dataType: "json", + success: function () {} + }); +}); + +$("body").on('change', '#globalSchedulerSwitchPageBtn', function(e) { + var ret = $(this).prop('checked'); + $.ajax({ + url: '/'+PACKAGE_NAME+'/ajax/' + MODULE_NAME + '/' + PAGE_NAME + '/scheduler', + type: "POST", + cache: false, + data: {scheduler : ret}, + dataType: "json", + success: function () {} + }); +}); + +$("body").on('click', '#globalOneExecuteBtn', function(e) { + e.preventDefault(); + $.ajax({ + url: '/'+PACKAGE_NAME+'/ajax/' + MODULE_NAME + '/one_execute', + type: "POST", + cache: false, + data: {}, + dataType: "json", + success: function (ret) { + if (ret=='scheduler' || ret=='thread') { + $.notify('작업을 시작하였습니다. ('+ret+')', { + type: 'success' + }); + } else if (ret == 'is_running') { + $.notify('작업중입니다.', { + type: 'warning' + }); + } else { + $.notify('작업 시작에 실패하였습니다.', { + type: 'warning' + }); + } + } + }); +}); + +$("body").on('click', '#globalOneExecutePageBtn', function(e) { + e.preventDefault(); + $.ajax({ + url: '/'+PACKAGE_NAME+'/ajax/' + MODULE_NAME + '/' + PAGE_NAME + '/one_execute', + type: "POST", + cache: false, + data: {sub:sub}, + dataType: "json", + success: function (ret) { + if (ret=='scheduler' || ret=='thread') { + $.notify('작업을 시작하였습니다. ('+ret+')', { + type: 'success' + }); + } else if (ret == 'is_running') { + $.notify('작업중입니다.', { + type: 'warning' + }); + } else { + $.notify('작업 시작에 실패하였습니다.', { + type: 'warning' + }); + } + } + }); +}); + +$("body").on('click', '#globalImmediatelyExecuteBtn', function(e){ + e.preventDefault(); + $.ajax({ + url: '/'+PACKAGE_NAME+'/ajax/' + MODULE_NAME + '/immediately_execute', + type: "POST", + cache: false, + data: {}, + dataType: "json", + success: function (ret) { + if (ret.msg != null) notify(ret.msg, ret.ret); + } + }); +}); + +$("body").on('click', '#globalImmediatelyExecutePageBtn', function(e){ + e.preventDefault(); + $.ajax({ + url: '/'+PACKAGE_NAME+'/ajax/' + MODULE_NAME + '/' + PAGE_NAME + '/immediately_execute', + type: "POST", + cache: false, + data: {}, + dataType: "json", + success: function (ret) { + if (ret.msg != null) notify(ret.msg, ret.ret); + } + }); +}); + + +$("body").on('click', '#globalDbDeleteBtn', function(e){ + e.preventDefault(); + document.getElementById("confirm_title").innerHTML = "DB 삭제"; + document.getElementById("confirm_body").innerHTML = "전체 목록을 삭제 하시겠습니까?"; + $('#confirm_button').attr('onclick', "globalDbDelete();"); + $("#confirm_modal").modal(); + return; +}); + +function globalDbDelete() { + $.ajax({ + url: '/'+PACKAGE_NAME+'/ajax/' + MODULE_NAME + '/reset_db', + type: "POST", + cache: false, + data: {}, + dataType: "json", + success: function (data) { + if (data) { + $.notify('삭제하였습니다.', { + type: 'success' + }); + } else { + $.notify('삭제에 실패하였습니다.',{ + type: 'warning' + }); + } + } + }); +} + +$("body").on('click', '#globalDbDeletePageBtn', function(e){ + e.preventDefault(); + document.getElementById("confirm_title").innerHTML = "DB 삭제"; + document.getElementById("confirm_body").innerHTML = "전체 목록을 삭제 하시겠습니까?"; + $('#confirm_button').attr('onclick', "globalDbDeletePage();"); + $("#confirm_modal").modal(); + return; +}); + +function globalDbDeletePage() { + $.ajax({ + url: '/'+PACKAGE_NAME+'/ajax/' + MODULE_NAME + '/' + PAGE_NAME + '/reset_db', + type: "POST", + cache: false, + data: {sub:sub}, + dataType: "json", + success: function (data) { + if (data) { + $.notify('삭제하였습니다.', { + type: 'success' + }); + } else { + $.notify('삭제에 실패하였습니다.',{ + type: 'warning' + }); + } + } + }); +} + + + /////////////////////////////////////// // Global - 함수 /////////////////////////////////////// @@ -180,6 +349,88 @@ function shutdown_confirm() { } + + +/////////////////////////////////////// +// 리스트 화면 기본 +/////////////////////////////////////// + + +function globalRequestSearch(page, move_top=true) { + var formData = getFormdata('#form_search') + formData += '&page=' + page; + $.ajax({ + url: '/' + PACKAGE_NAME + '/ajax/' + MODULE_NAME + '/web_list', + type: "POST", + cache: false, + data: formData, + dataType: "json", + success: function (data) { + current_data = data; + if (move_top) + window.scrollTo(0,0); + make_list(data.list) + make_page_html(data.paging) + } + }); +} + + + +function make_page_html(data) { + str = ' \ +
\ +
\ +
\ + \ +
\ +
\ + ' + document.getElementById("page1").innerHTML = str; + document.getElementById("page2").innerHTML = str; +} + + + +$("body").on('click', '#gloablSearchPageBtn', function(e){ + e.preventDefault(); + globalRequestSearch($(this).data('page'), false); +}); + +$("body").on('click', '#globalSearchSearchBtn', function(e){ + e.preventDefault(); + globalRequestSearch(1, false); +}); + +$("body").on('click', '#globalSearchResetBtn', function(e){ + e.preventDefault(); + $("#order").val('desc'); + $("#option1").val('all'); + $("#option2").val('all'); + $("#keyword").val(''); + globalRequestSearch(1, false); +}); + + + /////////////////////////////////////// // 파일 선택 모달 /////////////////////////////////////// diff --git a/lib/framework/static/js/ff_ui1.js b/lib/framework/static/js/ff_ui1.js index eb2006d..3ef2cb4 100644 --- a/lib/framework/static/js/ff_ui1.js +++ b/lib/framework/static/js/ff_ui1.js @@ -84,6 +84,14 @@ function j_row_info(left, right, l=2, r=8) { return str; } +function j_progress(id, width, label) { + var str = ''; + str += '
' + str += '
'; + str += '
'+label+'
'; + str += '
' + return str; +} @@ -110,6 +118,19 @@ function j_row_info(left, right, l=2, r=8) { + + + + + + + + +function make_log(key, value, left=2, right=10) { + row = m_col(left, key, aligh='right'); + row += m_col(right, value, aligh='left'); + return row; +} @@ -118,16 +139,106 @@ function text_color(text, color='red') { return '' + text + ''; } -function m_table(id, heads) { - str += ' \ - \ - \ - \ - \ - \ - \ - '; -} + + + +/////////////////////////////////////// +// UI - 확장설정 - dropdown +/////////////////////////////////////// + +document.addEventListener("DOMContentLoaded", function(){ + /////// Prevent closing from click inside dropdown + document.querySelectorAll('.dropdown-menu').forEach(function(element){ + element.addEventListener('click', function (e) { + e.stopPropagation(); + }); + }) + + // make it as accordion for smaller screens + if (window.innerWidth < 992) { + // close all inner dropdowns when parent is closed + document.querySelectorAll('.navbar .dropdown').forEach(function(everydropdown){ + everydropdown.addEventListener('hidden.bs.dropdown', function () { + // after dropdown is hidden, then find all submenus + this.querySelectorAll('.submenu').forEach(function(everysubmenu){ + // hide every submenu as well + everysubmenu.style.display = 'none'; + }); + }) + }); + + document.querySelectorAll('.dropdown-menu a').forEach(function(element){ + element.addEventListener('click', function (e) { + + let nextEl = this.nextElementSibling; + if(nextEl && nextEl.classList.contains('submenu')) { + // prevent opening link if link needs to open dropdown + e.preventDefault(); + console.log(nextEl); + if(nextEl.style.display == 'block'){ + nextEl.style.display = 'none'; + } else { + nextEl.style.display = 'block'; + } + + } + }); + }) + } +// end if innerWidth +}); +// DOMContentLoaded end +/////////////////////////////////////// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -218,14 +329,7 @@ function m_tab_content(name, content, active) { return str; } -function m_progress(id, width, label) { - var str = ''; - str += '
' - str += '
'; - str += '
'+label+'
'; - str += '
' - return str; -} + function m_progress2(id, width, label) { @@ -239,94 +343,12 @@ function m_progress2(id, width, label) { -function make_page_html(data) { - str = ' \ -
\ -
\ -
\ - \ -
\ -
\ - ' - document.getElementById("page1").innerHTML = str; - document.getElementById("page2").innerHTML = str; -} -function make_log(key, value, left=2, right=10) { - row = m_col(left, key, aligh='right'); - row += m_col(right, value, aligh='left'); - return row; -} + - -/////////////////////////////////////// -// UI - 확장설정 - dropdown -/////////////////////////////////////// - -document.addEventListener("DOMContentLoaded", function(){ - /////// Prevent closing from click inside dropdown - document.querySelectorAll('.dropdown-menu').forEach(function(element){ - element.addEventListener('click', function (e) { - e.stopPropagation(); - }); - }) - - // make it as accordion for smaller screens - if (window.innerWidth < 992) { - // close all inner dropdowns when parent is closed - document.querySelectorAll('.navbar .dropdown').forEach(function(everydropdown){ - everydropdown.addEventListener('hidden.bs.dropdown', function () { - // after dropdown is hidden, then find all submenus - this.querySelectorAll('.submenu').forEach(function(everysubmenu){ - // hide every submenu as well - everysubmenu.style.display = 'none'; - }); - }) - }); - - document.querySelectorAll('.dropdown-menu a').forEach(function(element){ - element.addEventListener('click', function (e) { - - let nextEl = this.nextElementSibling; - if(nextEl && nextEl.classList.contains('submenu')) { - // prevent opening link if link needs to open dropdown - e.preventDefault(); - console.log(nextEl); - if(nextEl.style.display == 'block'){ - nextEl.style.display = 'none'; - } else { - nextEl.style.display = 'block'; - } - - } - }); - }) - } -// end if innerWidth -}); -// DOMContentLoaded end -/////////////////////////////////////// \ No newline at end of file diff --git a/lib/framework/static/js/sjva_global1.js b/lib/framework/static/js/sjva_global1.js index 3e042db..a42bcc8 100644 --- a/lib/framework/static/js/sjva_global1.js +++ b/lib/framework/static/js/sjva_global1.js @@ -193,202 +193,14 @@ function streaming_kill(command, data={}) { // Global.. JS 파일로 뺄것 /////////////////////////////////////////////////////////////////////////////// -// 사용 on / off -$('#global_scheduler').change(function() { - var ret = $(this).prop('checked'); - $.ajax({ - url: '/'+package_name+'/ajax/scheduler', - type: "POST", - cache: false, - data: {scheduler : ret}, - dataType: "json", - success: function (list) { - } - }); -}); - -$('#global_scheduler_sub').change(function() { - var ret = $(this).prop('checked'); - $.ajax({ - url: '/'+package_name+'/ajax/scheduler', - type: "POST", - cache: false, - data: {scheduler : ret, sub:sub}, - dataType: "json", - success: function (list) { - } - }); -}); -function global_setting_save_function() { - var formData = getFormdata('#setting'); - $.ajax({ - url: '/'+package_name+'/ajax/setting_save', - type: "POST", - cache: false, - data: formData, - dataType: "json", - success: function (ret) { - if (ret) { - $.notify('설정을 저장하였습니다.', { - type: 'success' - }); - } else { - $.notify('설정 저장에 실패하였습니다.', { - type: 'warning' - }); - } - } - }); -} -$("#global_one_execute_btn").click(function(e) { -//$("body").on('click', '#one_execute_btn', function(e){ - e.preventDefault(); - $.ajax({ - url: '/' + package_name + '/ajax/one_execute', - type: "POST", - cache: false, - data: {}, - dataType: "json", - success: function (ret) { - if (ret=='scheduler' || ret=='thread') { - $.notify('작업을 시작하였습니다. ('+ret+')', { - type: 'success' - }); - } else if (ret == 'is_running') { - $.notify('작업중입니다.', { - type: 'warning' - }); - } else { - $.notify('작업 시작에 실패하였습니다.', { - type: 'warning' - }); - } - } - }); -}); - -$("#global_one_execute_sub_btn").click(function(e) { -//$("body").on('click', '#one_execute_btn', function(e){ - e.preventDefault(); - $.ajax({ - url: '/' + package_name + '/ajax/one_execute', - type: "POST", - cache: false, - data: {sub:sub}, - dataType: "json", - success: function (ret) { - if (ret=='scheduler' || ret=='thread') { - $.notify('작업을 시작하였습니다. ('+ret+')', { - type: 'success' - }); - } else if (ret == 'is_running') { - $.notify('작업중입니다.', { - type: 'warning' - }); - } else { - $.notify('작업 시작에 실패하였습니다.', { - type: 'warning' - }); - } - } - }); -}); -$("body").on('click', '#global_immediately_execute_sub_btn', function(e){ - e.preventDefault(); - $.ajax({ - url: '/' + package_name + '/ajax/immediately_execute', - type: "POST", - cache: false, - data: {sub:sub}, - dataType: "json", - success: function (ret) { - if (ret.msg != null) notify(ret.msg, ret.ret); - } - }); -}); -$("body").on('click', '#global_reset_db_btn', function(e){ - e.preventDefault(); - document.getElementById("confirm_title").innerHTML = "DB 삭제"; - document.getElementById("confirm_body").innerHTML = "전체 목록을 삭제 하시겠습니까?"; - $('#confirm_button').attr('onclick', "global_db_delete();"); - $("#confirm_modal").modal(); - return; -}); - -function global_db_delete() { - $.ajax({ - url: '/' + package_name + '/ajax/reset_db', - type: "POST", - cache: false, - data: {}, - dataType: "json", - success: function (data) { - if (data) { - $.notify('삭제하였습니다.', { - type: 'success' - }); - } else { - $.notify('삭제에 실패하였습니다.',{ - type: 'warning' - }); - } - } - }); -} -$("body").on('click', '#global_reset_db_sub_btn', function(e){ - e.preventDefault(); - document.getElementById("confirm_title").innerHTML = "DB 삭제"; - document.getElementById("confirm_body").innerHTML = "전체 목록을 삭제 하시겠습니까?"; - $('#confirm_button').attr('onclick', "global_db_delete_sub();"); - $("#confirm_modal").modal(); - return; -}); - -function global_db_delete_sub() { - $.ajax({ - url: '/' + package_name + '/ajax/reset_db', - type: "POST", - cache: false, - data: {sub:sub}, - dataType: "json", - success: function (data) { - if (data) { - $.notify('삭제하였습니다.', { - type: 'success' - }); - } else { - $.notify('삭제에 실패하였습니다.',{ - type: 'warning' - }); - } - } - }); -} -function global_sub_request_search(page, move_top=true) { - var formData = getFormdata('#form_search') - formData += '&page=' + page; - $.ajax({ - url: '/' + package_name + '/ajax/' + sub + '/web_list', - type: "POST", - cache: false, - data: formData, - dataType: "json", - success: function (data) { - current_data = data; - if (move_top) - window.scrollTo(0,0); - make_list(data.list) - make_page_html(data.paging) - } - }); -} + $("body").on('click', '#global_json_btn', function(e){ @@ -438,79 +250,11 @@ $("body").on('click', '#global_remove_btn', function(e) { -//####################################################### -//플러그인 - 모듈 - 서브 구조하에서 서브 관련 함수 -function global_send_command_sub(command, arg1, arg2, arg3, modal_title, callback) { - $.ajax({ - url: '/' + package_name + '/ajax/' + sub + '/' + sub2 + '/command', - type: "POST", - cache: false, - data:{command:command, arg1:arg1, arg2:arg2, arg3}, - dataType: "json", - success: function (ret) { - console.log(ret); - if (ret.msg != null) notify(ret.msg, ret.ret); - if (ret.modal != null) m_modal(ret.modal, modal_title, false); - if (ret.json != null) m_modal(ret.json, modal_title, true); - if (callback != null) callback(ret); - } - }); -} -$("body").on('click', '#global_one_execute_sublogic_btn', function(e){ - e.preventDefault(); - $.ajax({ - url: '/' + package_name + '/ajax/' + sub + '/' + sub2 + '/one_execute', - type: "POST", - cache: false, - data: {}, - dataType: "json", - success: function (ret) { - if (ret=='scheduler' || ret=='thread') { - $.notify('작업을 시작하였습니다. ('+ret+')', { - type: 'success' - }); - } else if (ret == 'is_running') { - $.notify('작업중입니다.', { - type: 'warning' - }); - } else { - $.notify('작업 시작에 실패하였습니다.', { - type: 'warning' - }); - } - } - }); -}); -$("body").on('click', '#global_immediately_execute_sublogic_btn', function(e){ - e.preventDefault(); - $.ajax({ - url: '/' + package_name + '/ajax/' + sub + '/' + sub2 + '/immediately_execute', - type: "POST", - cache: false, - data: {}, - dataType: "json", - success: function (ret) { - if (ret.msg != null) notify(ret.msg, ret.ret); - } - }); -}); -$('#global_scheduler_sublogic').change(function() { - var ret = $(this).prop('checked'); - $.ajax({ - url: '/'+package_name+'/ajax/' + sub + '/' + sub2 + '/scheduler', - type: "POST", - cache: false, - data: {scheduler : ret}, - dataType: "json", - success: function (list) { - } - }); -}); @@ -615,50 +359,3 @@ $('#global_scheduler_sublogic').change(function() { - - - - - - - - - - - - - -// 이동한 함수 - - - - -function global_send_command(command, data={}) { - data['command'] = command; - $.ajax({ - url: '/' + package_name + '/ajax/' + sub + '/command', - type: "POST", - cache: false, - data:data, - dataType: "json", - success: function (data) { - notify(data['msg'], data['ret']); - } - }); -} - -function global_send_command2(command, arg1, arg2, arg3, modal_title, callback) { - $.ajax({ - url: '/' + package_name + '/ajax/' + sub + '/command', - type: "POST", - cache: false, - data:{command:command, arg1:arg1, arg2:arg2, arg3}, - dataType: "json", - success: function (ret) { - if (ret.msg != null) notify(ret.msg, ret.ret); - if (ret.modal != null) m_modal(ret.modal, modal_title, false); - if (ret.json != null) m_modal(ret.json, modal_title, true); - if (callback != null) callback(ret); - } - }); -} diff --git a/lib/framework/static/js/sjva_ui14.js b/lib/framework/static/js/sjva_ui14.js index 1298f7a..5312110 100644 --- a/lib/framework/static/js/sjva_ui14.js +++ b/lib/framework/static/js/sjva_ui14.js @@ -97,57 +97,7 @@ function m_tab_content(name, content, active) { return str; } -function m_progress(id, width, label) { - var str = ''; - str += '
' - str += '
'; - str += '
'+label+'
'; - str += '
' - return str; -} - - -function m_progress2(id, width, label) { - var str = ''; - str += '
' - str += '
'; - str += '
'+label+'
'; - str += '
' - return str; -} - - -function make_page_html(data) { - str = ' \ -
\ -
\ -
\ - \ -
\ -
\ - ' - document.getElementById("page1").innerHTML = str; - document.getElementById("page2").innerHTML = str; -} diff --git a/lib/framework/templates/macro.html b/lib/framework/templates/macro.html index 97388d4..4cc1bd3 100644 --- a/lib/framework/templates/macro.html +++ b/lib/framework/templates/macro.html @@ -246,7 +246,25 @@ {% endmacro %} - + +{% macro setting_global_scheduler_button(is_include, is_running, id='scheduler', left='스케쥴링 작동', desc=['On : 스케쥴링 시작','Off : 스케쥴링 중지']) %} +{{ setting_top(left) }} +
+ {% if is_include == 'True' %} + + {% else %} + + {% endif %} + {% if is_running == 'True' %} + 동작중 + {% else %} + {% if is_include == 'True' %} + 대기중 + {% endif %} + {% endif %} +
+{{ setting_bottom(desc) }} +{% endmacro %} @@ -728,25 +746,7 @@ macros.setting_button_with_info([['toggle_btn', 'Toggle', [{'key':'category', 'v {% endmacro %} - -{% macro setting_global_scheduler_button(is_include, is_running, id='scheduler', left='스케쥴링 작동', desc=['On : 스케쥴링 시작','Off : 스케쥴링 중지']) %} -{{ setting_top(left) }} -
- {% if is_include == 'True' %} - - {% else %} - - {% endif %} - {% if is_running == 'True' %} - 동작중 - {% else %} - {% if is_include == 'True' %} - 대기중 - {% endif %} - {% endif %} -
-{{ setting_bottom(desc) }} -{% endmacro %} + {% macro setting_global_scheduler_sub_button(is_include, is_running, id='scheduler', left='스케쥴링 작동', desc=['On : 스케쥴링 시작','Off : 스케쥴링 중지']) %} {{ setting_top(left) }} diff --git a/lib/framework/version.py b/lib/framework/version.py index ac80dea..334bc04 100644 --- a/lib/framework/version.py +++ b/lib/framework/version.py @@ -1 +1 @@ -VERSION="4.0.30" \ No newline at end of file +VERSION="4.0.32" \ No newline at end of file diff --git a/lib/plugin/create_plugin.py b/lib/plugin/create_plugin.py index 0b840e6..2f89297 100644 --- a/lib/plugin/create_plugin.py +++ b/lib/plugin/create_plugin.py @@ -44,7 +44,7 @@ class PluginBase(object): self.ModelSetting = None if setting.get('use_db', True): db_path = os.path.join(F.config['path_data'], 'db', f'{self.package_name}.db') - F.app.config['SQLALCHEMY_BINDS'][self.package_name] = f"sqlite:///{db_path}" + F.app.config['SQLALCHEMY_BINDS'][self.package_name] = f"sqlite:///{db_path}?check_same_thread=False" if setting.get('use_default_setting', True): self.ModelSetting = get_model_setting(self.package_name, self.logger) diff --git a/lib/plugin/logic.py b/lib/plugin/logic.py index a1186da..36d3bc8 100644 --- a/lib/plugin/logic.py +++ b/lib/plugin/logic.py @@ -84,47 +84,47 @@ class Logic(object): self.P.logger.error(traceback.format_exc()) - def scheduler_start(self, sub): + def scheduler_start(self, module_name): try: - job_id = '%s_%s' % (self.P.package_name, sub) - module = self.get_module(sub) - job = Job(self.P.package_name, job_id, module.get_scheduler_interval(), self.scheduler_function, module.get_scheduler_desc(), args=sub) + job_id = '%s_%s' % (self.P.package_name, module_name) + module = self.get_module(module_name) + job = Job(self.P.package_name, job_id, module.get_scheduler_interval(), self.scheduler_function, module.get_scheduler_desc(), args=module_name) F.scheduler.add_job_instance(job) except Exception as e: self.P.logger.error(f'Exception:{str(e)}') self.P.logger.error(traceback.format_exc()) - def scheduler_stop(self, sub): + def scheduler_stop(self, module_name): try: - job_id = '%s_%s' % (self.P.package_name, sub) + job_id = '%s_%s' % (self.P.package_name, module_name) F.scheduler.remove_job(job_id) except Exception as e: self.P.logger.error(f'Exception:{str(e)}') self.P.logger.error(traceback.format_exc()) - def scheduler_function(self, sub): + def scheduler_function(self, module_name): try: - module = self.get_module(sub) + module = self.get_module(module_name) module.scheduler_function() except Exception as e: self.P.logger.error(f'Exception:{str(e)}') self.P.logger.error(traceback.format_exc()) - def reset_db(self,sub): + def reset_db(self, module_name): try: - module = self.get_module(sub) + module = self.get_module(module_name) return module.reset_db() except Exception as e: self.P.logger.error(f'Exception:{str(e)}') self.P.logger.error(traceback.format_exc()) - def one_execute(self, sub): - self.P.logger.debug('one_execute :%s', sub) + def one_execute(self, module_name): + self.P.logger.debug('one_execute :%s', module_name) try: - job_id = '%s_%s' % (self.P.package_name, sub) + job_id = '%s_%s' % (self.P.package_name, module_name) if F.scheduler.is_include(job_id): if F.scheduler.is_running(job_id): ret = 'is_running' @@ -134,7 +134,7 @@ class Logic(object): else: def func(): time.sleep(2) - self.scheduler_function(sub) + self.scheduler_function(module_name) threading.Thread(target=func, args=()).start() ret = 'thread' except Exception as e: @@ -143,12 +143,12 @@ class Logic(object): ret = 'fail' return ret - def immediately_execute(self, sub): - self.P.logger.debug('immediately_execute :%s', sub) + def immediately_execute(self, module_name): + self.P.logger.debug('immediately_execute :%s', module_name) try: def func(): time.sleep(1) - self.scheduler_function(sub) + self.scheduler_function(module_name) threading.Thread(target=func, args=()).start() ret = {'ret':'success', 'msg':'실행합니다.'} except Exception as e: @@ -175,6 +175,65 @@ class Logic(object): self.P.logger.error(f'Exception:{str(e)}') self.P.logger.error(traceback.format_exc()) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ####################################################### # 플러그인 - 모듈 - 페이지 구조하에서 서브 관련 함수 diff --git a/lib/plugin/logic_module_base.py b/lib/plugin/logic_module_base.py index b7117d7..ec56521 100644 --- a/lib/plugin/logic_module_base.py +++ b/lib/plugin/logic_module_base.py @@ -14,6 +14,16 @@ class PluginModuleBase(object): self.socketio_list = None self.page_list = None + def get_module(self, module_name): + try: + for module in self.P.module_list: + if module.name == module_name: + return module + except Exception as e: + self.P.logger.error(f'Exception:{str(e)}') + self.P.logger.error(traceback.format_exc()) + + # set_module_list 대응 def set_page_list(self, page_list): try: @@ -87,7 +97,7 @@ class PluginModuleBase(object): def get_first_menu(self): return self.first_menu - def get_scheduler_name(self): + def get_scheduler_id(self): return '%s_%s' % (self.P.package_name, self.name) def dump(self, data): diff --git a/lib/plugin/model_base.py b/lib/plugin/model_base.py index fadc531..ca3c4b3 100644 --- a/lib/plugin/model_base.py +++ b/lib/plugin/model_base.py @@ -1,5 +1,5 @@ import traceback -from datetime import datetime +from datetime import datetime, timedelta from framework import F @@ -8,7 +8,7 @@ class ModelBase(F.db.Model): __abstract__ = True __table_args__ = {'mysql_collate': 'utf8_general_ci'} model_setting = None - logger = None + P = None def __repr__(self): return repr(self.as_dict()) @@ -24,8 +24,8 @@ class ModelBase(F.db.Model): F.db.session.commit() return self except Exception as e: - self.logger.error(f'Exception:{str(e)}') - self.logger.error(traceback.format_exc()) + self.P.logger.error(f'Exception:{str(e)}') + self.P.logger.error(traceback.format_exc()) @classmethod def get_paging_info(cls, count, current_page, page_size): @@ -48,8 +48,8 @@ class ModelBase(F.db.Model): F.logger.debug('paging : c:%s %s %s %s %s %s', count, paging['total_page'], paging['prev_page'], paging['next_page'] , paging['start_page'], paging['last_page']) return paging except Exception as e: - F.logger.error(f'Exception:{str(e)}') - F.logger.error(traceback.format_exc()) + cls.P.logger.error(f'Exception:{str(e)}') + cls.P.logger.error(traceback.format_exc()) @classmethod @@ -58,8 +58,8 @@ class ModelBase(F.db.Model): with F.app.app_context(): return F.db.session.query(cls).filter_by(id=int(id)).first() except Exception as e: - F.logger.error(f'Exception:{str(e)}') - F.logger.error(traceback.format_exc()) + cls.P.logger.error(f'Exception:{str(e)}') + cls.P.logger.error(traceback.format_exc()) @classmethod @@ -71,8 +71,8 @@ class ModelBase(F.db.Model): tmp = [x.as_dict() for x in tmp] return tmp except Exception as e: - F.logger.error(f'Exception:{str(e)}') - F.logger.error(traceback.format_exc()) + cls.P.logger.error(f'Exception:{str(e)}') + cls.P.logger.error(traceback.format_exc()) @@ -84,20 +84,32 @@ class ModelBase(F.db.Model): F.db.session.commit() return True except Exception as e: - F.logger.error(f'Exception:{str(e)}') - F.logger.error(traceback.format_exc()) + cls.P.logger.error(f'Exception:{str(e)}') + cls.P.logger.error(traceback.format_exc()) return False @classmethod - def delete_all(cls): + def delete_all(cls, days=None): try: with F.app.app_context(): - F.db.session.query(cls).delete() - F.db.session.commit() + if days == None: + F.db.session.query(cls).delete() + F.db.session.commit() + else: + now = datetime.datetime.now() + ago = now - datetime.timedelta(days=days) + + ret = F.db.session.query(cls).filter(cls.created_time > ago).delete() + cls.P.debug(ret) + + + + + return True except Exception as e: - F.logger.error(f'Exception:{str(e)}') - F.logger.error(traceback.format_exc()) + cls.P.logger.error(f'Exception:{str(e)}') + cls.P.logger.error(traceback.format_exc()) return False @@ -111,12 +123,12 @@ class ModelBase(F.db.Model): if 'page' in req.form: page = int(req.form['page']) if 'keyword' in req.form: - search = req.form['keyword'] + search = req.form['keyword'].strip() option1 = req.form.get('option1', 'all') option2 = req.form.get('option2', 'all') order = req.form['order'] if 'order' in req.form else 'desc' - query = cls.make_query(order=order, search=search, option1=option1, option2=option2) + query = cls.make_query(req, order=order, search=search, option1=option1, option2=option2) count = query.count() query = query.limit(page_size).offset((page-1)*page_size) F.logger.debug('cls count:%s', count) @@ -124,21 +136,21 @@ class ModelBase(F.db.Model): ret['list'] = [item.as_dict() for item in lists] ret['paging'] = cls.get_paging_info(count, page, page_size) try: - if cls.model_setting is not None and cls.__tablename__ is not None: - cls.model_setting.set(f'{cls.__tablename__}_last_list_option', f'{order}|{page}|{search}|{option1}|{option2}') + if cls.P.ModelSetting is not None and cls.__tablename__ is not None: + cls.P.ModelSetting.set(f'{cls.__tablename__}_last_list_option', f'{order}|{page}|{search}|{option1}|{option2}') except Exception as e: F.logger.error('Exception:%s', e) F.logger.error(traceback.format_exc()) F.logger.error(f'{cls.__tablename__}_last_list_option ERROR!' ) return ret except Exception as e: - F.logger.error('Exception:%s', e) - F.logger.error(traceback.format_exc()) + cls.P.logger.error('Exception:%s', e) + cls.P.logger.error(traceback.format_exc()) # 오버라이딩 @classmethod - def make_query(cls, order='desc', search='', option1='all', option2='all'): + def make_query(cls, req, order='desc', search='', option1='all', option2='all'): with F.app.app_context(): query = F.db.session.query(cls) return query diff --git a/lib/plugin/model_setting.py b/lib/plugin/model_setting.py index 853d65f..3a93a88 100644 --- a/lib/plugin/model_setting.py +++ b/lib/plugin/model_setting.py @@ -101,7 +101,7 @@ def get_model_setting(package_name, logger, table_name=None): for key, value in req.form.items(): if key in ['scheduler', 'is_running']: continue - if key.startswith('global_') or key.startswith('tmp_') or key.startswith('_'): + if key.startswith('global') or key.startswith('tmp_') or key.startswith('_'): continue #logger.debug('Key:%s Value:%s', key, value) if ModelSetting.get(key) != value: diff --git a/lib/plugin/route.py b/lib/plugin/route.py index f0d5253..a1aca47 100644 --- a/lib/plugin/route.py +++ b/lib/plugin/route.py @@ -92,42 +92,37 @@ def default_route(P): for module in P.module_list: module.setting_save_after(change_list) return jsonify(ret) - elif sub == 'scheduler': - sub = request.form['sub'] - go = request.form['scheduler'] - P.logger.debug('scheduler :%s', go) - if go == 'true': - P.logic.scheduler_start(sub) - else: - P.logic.scheduler_stop(sub) - return jsonify(go) - elif sub == 'reset_db': - sub = request.form['sub'] - ret = P.logic.reset_db(sub) - return jsonify(ret) - elif sub == 'one_execute': - sub = request.form['sub'] - ret = P.logic.one_execute(sub) - return jsonify(ret) - elif sub == 'immediately_execute': - sub = request.form['sub'] - ret = P.logic.immediately_execute(sub) - return jsonify(ret) + except Exception as exception: P.logger.error('Exception:%s', exception) P.logger.error(traceback.format_exc()) - @P.blueprint.route('/ajax//', methods=['GET', 'POST']) + @P.blueprint.route('/ajax//', methods=['GET', 'POST']) @login_required - def second_ajax(mod, cmd): + def second_ajax(module_name, cmd): try: for module in P.module_list: - if mod == module.name: + if module_name == module.name: if cmd == 'command': return module.process_command(request.form['command'], request.form.get('arg1'), request.form.get('arg2'), request.form.get('arg3'), request) else: return module.process_ajax(cmd, request) - + elif cmd == 'scheduler': + go = request.form['scheduler'] + if go == 'true': + P.logic.scheduler_start(module_name) + else: + P.logic.scheduler_stop(module_name) + return jsonify(go) + elif cmd == 'reset_db': + ret = P.logic.reset_db(module_name) + return jsonify(ret) + elif cmd == 'one_execute': + ret = P.logic.one_execute(module_name) + return jsonify(ret) + elif cmd == 'immediately_execute': + ret = P.logic.immediately_execute(module_name) + return jsonify(ret) except Exception as exception: P.logger.error('Exception:%s', exception) P.logger.error(traceback.format_exc())
NO물어본 숫자스트라이크가능한 숫자 수Action