Przeglądaj źródła

Merge pull request #2105 from openNAMU/dev

Dev
잉여개발기 2 lat temu
rodzic
commit
c9ecae509d

+ 5 - 3
app.py

@@ -516,6 +516,9 @@ app.route('/xref_page/<int:num>/<everything:name>')(view_xref)
 app.route('/xref_this/<everything:name>', defaults = { 'xref_type' : 2 })(view_xref)
 app.route('/xref_this_page/<int:num>/<everything:name>', defaults = { 'xref_type' : 2 })(view_xref)
 
+app.route('/doc_watch_list/<int:num>/<everything:name>', defaults = { 'db_set' : db_set_str, 'do_type' : 'watch_list' })(w_watch_list)
+app.route('/doc_star_doc/<int:num>/<everything:name>', defaults = { 'db_set' : db_set_str, 'do_type' : 'star_doc' })(w_watch_list)
+
 app.route('/raw/<everything:name>')(view_w_raw)
 app.route('/raw_acl/<everything:name>', defaults = { 'doc_acl' : 'on' })(view_w_raw)
 app.route('/raw_rev/<int:rev>/<everything:name>')(view_w_raw)
@@ -526,7 +529,6 @@ app.route('/down/<everything:name>')(view_down)
 
 app.route('/acl/<everything:name>', methods = ['POST', 'GET'])(view_set)
 
-# everything 다음에 추가 붙은 경우에 대해서 재검토 필요 (진행중)
 app.route('/w_from/<everything:name>', defaults = { 'do_type' : 'from' })(view_w)
 app.route('/w/<everything:name>')(view_w)
 
@@ -681,8 +683,8 @@ app.route('/api/raw_exist/<everything:name>', defaults = { 'exist_check' : 'on',
 app.route('/api/raw_rev/<int(signed = True):rev>/<everything:name>', defaults = { 'db_set' : db_set_str })(api_w_raw)
 app.route('/api/raw/<everything:name>', defaults = { 'db_set' : db_set_str })(api_w_raw)
 
-app.route('/api/star_doc/<int:num>/<everything:name>', defaults = { 'db_set' : db_set_str, 'do_type' : 'star_doc' })(api_w_watch_list)
-app.route('/api/watch_list/<int:num>/<everything:name>', defaults = { 'db_set' : db_set_str })(api_w_watch_list)
+app.route('/api/doc_star_doc/<int:num>/<everything:name>', defaults = { 'db_set' : db_set_str, 'do_type' : 'star_doc' })(api_w_watch_list)
+app.route('/api/doc_watch_list/<int:num>/<everything:name>', defaults = { 'db_set' : db_set_str })(api_w_watch_list)
 
 app.route('/api/xref/<int:num>/<everything:name>', defaults = { 'db_set' : db_set_str })(api_w_xref)
 app.route('/api/xref_this/<int:num>/<everything:name>', defaults = { 'xref_type' : '2', 'db_set' : db_set_str })(api_w_xref)

+ 2 - 0
route/__init__.py

@@ -168,6 +168,8 @@ from route.vote_end import vote_end
 from route.vote_list import vote_list
 from route.vote_select import vote_select
 
+from route.n_w_watch_list import w_watch_list
+
 from route.go_api_func_sha224 import api_func_sha224
 from route.go_api_func_ip import api_func_ip
 

+ 1 - 1
route/bbs_w_post.py

@@ -297,7 +297,7 @@ def bbs_w_post(bbs_num = '', post_num = ''):
                     <form method="post">
                         ''' + bbs_comment_form + '''
                     </form>
-                    <script src="/views/main_css/js/route/bbs_w_post.js"></script>
+                    <script src="/views/main_css/js/route/bbs_w_post.js''' + cache_v() + '''"></script>
                 '''
 
                 return easy_minify(flask.render_template(skin_check(),

+ 9 - 2
route/edit.py

@@ -23,14 +23,19 @@ def edit_timeout(func, args = (), timeout = 3):
         pool.join()
         return 0
         
-def edit_editor(curs, ip, data_main = '', do_type = 'edit', addon = ''):
+def edit_editor(curs, ip, data_main = '', do_type = 'edit', addon = '', name = ''):
     monaco_editor_top = ''
     editor_display = ''
     monaco_display = ''
+    div = ''
 
     if do_type == 'edit':
         curs.execute(db_change('select data from other where name = "edit_help"'))
         sql_d = curs.fetchall()
+
+        curs.execute(db_change("select set_data from data_set where doc_name = ? and set_name = 'document_top'"), [name])
+        body = curs.fetchall()
+        div = body[0][0] if body else ''
     elif do_type == 'bbs':
         curs.execute(db_change('select data from other where name = "bbs_help"'))
         sql_d = curs.fetchall()
@@ -72,6 +77,8 @@ def edit_editor(curs, ip, data_main = '', do_type = 'edit', addon = ''):
             ''' + edit_button() + '''
         </div>
         
+        ''' + div + '''
+
         <div id="opennamu_monaco_editor" class="''' + textarea_size + '''" ''' + monaco_display + '''></div>
         <textarea id="opennamu_edit_textarea" ''' + editor_display + ''' class="''' + textarea_size + '''" name="content" placeholder="''' + p_text + '''">''' + html.escape(data_main) + '''</textarea>
         <hr class="main_hr">
@@ -341,7 +348,7 @@ def edit(name = 'Test', section = 0, do_type = ''):
                         <input placeholder="''' + load_lang('why') + '''" name="send">
                         <hr class="main_hr">
                         
-                        ''' + edit_editor(curs, ip, data_section, addon = get_edit_text_bottom_check_box() + get_edit_text_bottom()) + '''
+                        ''' + edit_editor(curs, ip, data_section, addon = get_edit_text_bottom_check_box() + get_edit_text_bottom(), name = name) + '''
                     </form>
                 ''',
                 menu = [

+ 0 - 1
route/edit_delete.py

@@ -43,7 +43,6 @@ def edit_delete(name):
                     ip,
                     send,
                     leng,
-                    t_check = 'delete',
                     mode = 'delete'
                 )
 

+ 1 - 1
route/edit_move.py

@@ -120,7 +120,7 @@ def edit_move(name):
                             ip, 
                             send, 
                             '0',
-                            t_check = '<a>' + title_name[0] + '</a>  <a>' + title_name[1] + '</a>',
+                            t_check = '<a>' + title_name[0] + '</a>  <a>' + title_name[1] + '</a>',
                             mode = 'move'
                         )
                 elif move_option != 'none':

+ 22 - 0
route/n_w_watch_list.py

@@ -0,0 +1,22 @@
+from .tool.func import *
+
+from .go_api_w_watch_list import api_w_watch_list
+
+def w_watch_list(db_set, name, num = 1, do_type = 'watch_list'):
+    with get_db_connect() as conn:
+        data = '<a href="/doc_watch_list/1/' + url_pas(name) + '">(' + load_lang('watchlist') + ')</a> <a href="/doc_star_doc/1/' + url_pas(name) + '">(' + load_lang('star_doc') + ')</a>'
+        data += '<ul class="opennamu_ul">'
+        
+        list_data = json.loads(api_w_watch_list(db_set, name, do_type, num).data)
+        data += ''.join(['<li><span class="opennamu_render_ip">' + for_a + '</span></li>' for for_a in list_data])
+
+        data += '</ul>'
+        data += '<script>opennamu_do_ip_render();</script>'
+
+        data += get_next_page_bottom('/doc_' + do_type + '/{}/' + url_pas(name), num, list_data)
+
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang(do_type if do_type == 'star_doc' else 'watchlist') + ')', 0])],
+            data = data,
+            menu = [['w/' + url_pas(name), load_lang('return')]]
+        ))

+ 5 - 3
route/tool/func.py

@@ -963,7 +963,7 @@ def easy_minify(data, tool = None):
             return data
             
         return '''
-            <script src="/views/main_css/js/route/wiki_access_password.js"></script>
+            <script src="/views/main_css/js/route/wiki_access_password.js''' + cache_v() + '''"></script>
             <h2>''' + load_lang('error_password_require_for_wiki_access') + '''</h2>
             <input type="password" id="wiki_access">
             <input type="submit" onclick="opennamu_do_wiki_access();">
@@ -1049,6 +1049,9 @@ def skin_check(set_n = 0):
         else:
             return skin
     
+def cache_v():
+    return '.cache_v216'
+
 def wiki_css(data):
     global global_wiki_set
 
@@ -1058,8 +1061,7 @@ def wiki_css(data):
     data_css = ''
     data_css_dark = ''
 
-    data_css_ver = '214'
-    data_css_ver = '.cache_v' + data_css_ver
+    data_css_ver = cache_v()
 
     if 'main_css' in global_wiki_set:
         data_css = global_wiki_set['main_css']

+ 109 - 80
route/tool/func_render_namumark.py

@@ -604,6 +604,30 @@ class class_do_render_namumark:
 
                 data_name = self.get_tool_data_storage('<span id="' + main_text + '">', '</span>', match_org.group(0))
 
+                return '<' + data_name + '></' + data_name + '>'
+            elif name_data == 'username':
+                data = re.findall(macro_split_regex, match[1])
+
+                # get option
+                user_name = ''
+                render = 1
+                for for_a in data:
+                    data_sub = re.search(macro_split_sub_regex, for_a)
+                    if data_sub:
+                        data_sub = data_sub.groups()
+                        data_sub = [data_sub[0].lower(), data_sub[1]]
+
+                        if data_sub[0] == 'load_name':
+                            if data_sub[1] == '1':
+                                user_name = self.ip
+                        elif data_sub[0] == 'render':
+                            if data_sub[1] == '0':
+                                render = 0
+                    else:
+                        user_name = for_a
+
+                data_name = self.get_tool_data_storage('<span class="' + ('opennamu_render_ip' if render == 1 else '') + '">' + user_name + '</span>', '', match_org.group(0))
+
                 return '<' + data_name + '></' + data_name + '>'
             elif name_data == 'timeif':
                 data = re.findall(macro_split_regex, match[1])
@@ -1465,103 +1489,107 @@ class class_do_render_namumark:
 
     def do_render_redirect(self):
         match = re.search(r'^<back_br>\n#(?:redirect|넘겨주기) ([^\n]+)', self.render_data, flags = re.I)
-        if match and self.doc_set['doc_type'] == 'view':
-            link_data_full = match.group(0)
-            link_main = match.group(1)
-
-            link_inter_name = ''
-
-            link_inter_regex = re.compile('^(?:inter|인터):([^:]+):', flags = re.I)
-            inter_check = re.search(link_inter_regex, link_main)
-            if not inter_check:
-                # under page & fix url
-                link_main = self.get_tool_link_fix(link_main, 'redirect')
-            else:
-                link_inter_name = inter_check.group(1)
-                link_main = re.sub(link_inter_regex, '', link_main)
-
-            # sharp
-            link_main = link_main.replace('&#x27;', '<link_single>')
-            link_data_sharp_regex = r'#([^#]+)$'
-            link_data_sharp = re.search(link_data_sharp_regex, link_main)
-            if link_data_sharp:
-                link_data_sharp = link_data_sharp.group(1)
-                link_data_sharp = html.unescape(link_data_sharp)
-                link_data_sharp = '#' + url_pas(link_data_sharp)
-
-                link_main = re.sub(link_data_sharp_regex, '', link_main)
-            else:
-                link_data_sharp = ''
-            
-            link_main = link_main.replace('<link_single>', '&#x27;')
+        if match:
+            if self.doc_set['doc_type'] == 'view':
+                link_data_full = match.group(0)
+                link_main = match.group(1)
 
-            if not inter_check:
-                # main link fix
-                link_main = self.get_tool_data_restore(link_main, do_type = 'slash')
-                link_main = html.unescape(link_main)
+                link_inter_name = ''
 
-                link_exist = 1
+                link_inter_regex = re.compile('^(?:inter|인터):([^:]+):', flags = re.I)
+                inter_check = re.search(link_inter_regex, link_main)
+                if not inter_check:
+                    # under page & fix url
+                    link_main = self.get_tool_link_fix(link_main, 'redirect')
+                else:
+                    link_inter_name = inter_check.group(1)
+                    link_main = re.sub(link_inter_regex, '', link_main)
 
-                self.curs.execute(db_change("select title from data where title = ?" + self.link_case_insensitive), [link_main])
-                db_data = self.curs.fetchall()
-                if not db_data:
-                    if not link_main in self.data_backlink:
-                        self.data_backlink[link_main] = {}
+                # sharp
+                link_main = link_main.replace('&#x27;', '<link_single>')
+                link_data_sharp_regex = r'#([^#]+)$'
+                link_data_sharp = re.search(link_data_sharp_regex, link_main)
+                if link_data_sharp:
+                    link_data_sharp = link_data_sharp.group(1)
+                    link_data_sharp = html.unescape(link_data_sharp)
+                    link_data_sharp = '#' + url_pas(link_data_sharp)
 
-                    self.data_backlink[link_main]['no'] = ''
-                    link_exist = 0
+                    link_main = re.sub(link_data_sharp_regex, '', link_main)
                 else:
-                    link_main = db_data[0][0]
-                    if not link_main in self.data_backlink:
-                        self.data_backlink[link_main] = {}
+                    link_data_sharp = ''
+                
+                link_main = link_main.replace('<link_single>', '&#x27;')
 
-                self.data_backlink[link_main]['redirect'] = ''
+                if not inter_check:
+                    # main link fix
+                    link_main = self.get_tool_data_restore(link_main, do_type = 'slash')
+                    link_main = html.unescape(link_main)
 
-                link_main = url_pas(link_main)
-                if link_main != '':
-                    link_main = '/w_from/' + link_main
+                    link_exist = 1
 
-                self.data_redirect = 1
-                if link_exist == 1:
-                    if self.doc_set['doc_from'] != '':
-                        data_name = self.get_tool_data_storage('<a href="' + link_main + link_data_sharp + '">(GO)</a>', '', link_data_full)
+                    self.curs.execute(db_change("select title from data where title = ?" + self.link_case_insensitive), [link_main])
+                    db_data = self.curs.fetchall()
+                    if not db_data:
+                        if not link_main in self.data_backlink:
+                            self.data_backlink[link_main] = {}
+
+                        self.data_backlink[link_main]['no'] = ''
+                        link_exist = 0
                     else:
-                        data_name = self.get_tool_data_storage('<meta http-equiv="refresh" content="0; url=' + link_main + link_data_sharp + '">', '', link_data_full)
-                else:
-                    data_name = self.get_tool_data_storage('', '', link_data_full)
+                        link_main = db_data[0][0]
+                        if not link_main in self.data_backlink:
+                            self.data_backlink[link_main] = {}
+
+                    self.data_backlink[link_main]['redirect'] = ''
 
-                self.render_data = '<' + data_name + '></' + data_name + '>'
-            else:
-                self.curs.execute(db_change("select plus, plus_t from html_filter where kind = 'inter_wiki' and html = ?"), [link_inter_name])
-                db_data = self.curs.fetchall()
-                if db_data:
                     link_main = url_pas(link_main)
-                    link_main = db_data[0][0] + link_main
+                    if link_main != '':
+                        link_main = '/w_from/' + link_main
 
-                    link_sub_storage = match.group(1)
-                    link_sub_storage = re.sub(link_inter_regex, '', link_sub_storage)
+                    self.data_redirect = 1
+                    if link_exist == 1:
+                        if self.doc_set['doc_from'] != '':
+                            data_name = self.get_tool_data_storage('<a href="' + link_main + link_data_sharp + '">(GO)</a>', '', link_data_full)
+                        else:
+                            data_name = self.get_tool_data_storage('<meta http-equiv="refresh" content="0; url=' + link_main + link_data_sharp + '">', '', link_data_full)
+                    else:
+                        data_name = self.get_tool_data_storage('', '', link_data_full)
 
-                    link_inter_icon = link_inter_name + ':'
-                    if db_data[0][1] != '':
-                        link_inter_icon = db_data[0][1]
+                    self.render_data = '<' + data_name + '></' + data_name + '>'
+                else:
+                    self.curs.execute(db_change("select plus, plus_t from html_filter where kind = 'inter_wiki' and html = ?"), [link_inter_name])
+                    db_data = self.curs.fetchall()
+                    if db_data:
+                        link_main = url_pas(link_main)
+                        link_main = db_data[0][0] + link_main
 
-                    link_sub_storage = link_inter_icon + link_sub_storage
+                        link_sub_storage = match.group(1)
+                        link_sub_storage = re.sub(link_inter_regex, '', link_sub_storage)
 
-                    self.curs.execute(db_change("select plus_t from html_filter where kind = 'inter_wiki_sub' and html = ?"), [link_inter_name])
-                    db_data = self.curs.fetchall()
-                    if db_data and db_data[0][0] == 'under_bar':
-                        link_main = link_main.replace('%20', '_')
+                        link_inter_icon = link_inter_name + ':'
+                        if db_data[0][1] != '':
+                            link_inter_icon = db_data[0][1]
 
-                    self.data_redirect = 1
-                    if 'doc_from' in self.doc_set:
-                        data_name = self.get_tool_data_storage('<a href="' + link_main + link_data_sharp + '">(GO)</a>', '', link_data_full)
+                        link_sub_storage = link_inter_icon + link_sub_storage
+
+                        self.curs.execute(db_change("select plus_t from html_filter where kind = 'inter_wiki_sub' and html = ?"), [link_inter_name])
+                        db_data = self.curs.fetchall()
+                        if db_data and db_data[0][0] == 'under_bar':
+                            link_main = link_main.replace('%20', '_')
+
+                        self.data_redirect = 1
+                        if 'doc_from' in self.doc_set:
+                            data_name = self.get_tool_data_storage('<a href="' + link_main + link_data_sharp + '">(GO)</a>', '', link_data_full)
+                        else:
+                            data_name = self.get_tool_data_storage('<meta http-equiv="refresh" content="5; url=' + link_main + link_data_sharp + '">', link_sub_storage + ' - After 5s', link_data_full)
+                    
+                        self.render_data = '<' + data_name + '></' + data_name + '>'
                     else:
-                        data_name = self.get_tool_data_storage('<meta http-equiv="refresh" content="5; url=' + link_main + link_data_sharp + '">', link_sub_storage + ' - After 5s', link_data_full)
-                
-                    self.render_data = '<' + data_name + '></' + data_name + '>'
-                else:
-                    self.data_redirect = 1
-                    self.render_data = ''
+                        self.data_redirect = 1
+                        self.render_data = ''
+            else:
+                self.data_redirect = 1
+                self.render_data = ''
 
     def do_render_table(self):
         self.render_data = re.sub(r'\n +\|\|', '\n||', self.render_data)
@@ -2325,6 +2353,7 @@ class class_do_render_namumark:
             if(window.location.hash !== '' && document.getElementById(window.location.hash.replace(/^#/, ''))) {
                 document.getElementById(window.location.hash.replace(/^#/, '')).focus();
             }\n
+            opennamu_do_ip_render();\n
         '''
 
     def __call__(self):

+ 32 - 3
route/view_set.py

@@ -79,8 +79,16 @@ def view_set(name = 'Test'):
 
             markup_data = markup_data if markup_data != '' else 'normal'
 
-            if user_page == 1:
-                admin_check(5, check_data + ' (' + all_d + ')' + ' (' + markup_data + ')')
+            if admin_check() == 1:
+                document_top = flask.request.form.get('document_top', '')
+                curs.execute(db_change("delete from data_set where doc_name = ? and set_name = 'document_top'"), [name])
+                curs.execute(db_change("insert into data_set (doc_name, doc_rev, set_name, set_data) values (?, '', 'document_top', ?)"), [name, document_top])
+                
+                document_editor_top = flask.request.form.get('document_editor_top', '')
+                curs.execute(db_change("delete from data_set where doc_name = ? and set_name = 'document_editor_top'"), [name])
+                curs.execute(db_change("insert into data_set (doc_name, doc_rev, set_name, set_data) values (?, '', 'document_editor_top', ?)"), [name, document_editor_top])
+
+            admin_check(5, check_data)
 
             conn.commit()
 
@@ -175,6 +183,27 @@ def view_set(name = 'Test'):
             markup_html = '<select name="document_markup" ' + check_ok + '>' + markup_html + '</select>'
 
             data += markup_html
+
+            save_button = '<button type="submit" ' + check_ok + '>' + load_lang('save') + '</button>'
+            if admin_check() != 1:
+                check_ok = 'disabled'
+
+            curs.execute(db_change("select set_data from data_set where doc_name = ? and set_name = 'document_top'"), [name])
+            db_data = curs.fetchall()
+            document_top = db_data[0][0] if db_data and db_data[0][0] != '' else ''
+
+            curs.execute(db_change("select set_data from data_set where doc_name = ? and set_name = 'document_editor_top'"), [name])
+            db_data = curs.fetchall()
+            document_editor_top = db_data[0][0] if db_data and db_data[0][0] != '' else ''
+
+            data += '''
+                <h2>''' + load_lang('document_top') + ''' (HTML)</h2>
+                <textarea ''' + check_ok + ''' class="opennamu_textarea_100" name="document_top">''' + html.escape(document_top) + '''</textarea>
+                
+                <h2>''' + load_lang('document_editor_top') + ''' (HTML)</h2>
+                <textarea ''' + check_ok + ''' class="opennamu_textarea_100" name="document_editor_top">''' + html.escape(document_editor_top) + '''</textarea>
+            '''
+            
             data += '<hr class="main_hr">'
 
             return easy_minify(flask.render_template(skin_check(),
@@ -184,7 +213,7 @@ def view_set(name = 'Test'):
                         <a href="/setting/acl">(''' + load_lang('main_acl_setting') + ''')</a>
                         <hr class="main_hr">
                         ''' + render_simple_set(data) + '''
-                        <button type="submit" ''' + check_ok + '''>''' + load_lang('save') + '''</button>
+                        ''' + save_button + '''
                     </form>
                 ''',
                 menu = [

+ 21 - 20
route/view_w.py

@@ -5,6 +5,7 @@ def view_w(name = 'Test', do_type = ''):
         curs = conn.cursor()
 
         sub = 0
+        history_color = 0
         menu = []
 
         user_doc = ''
@@ -160,12 +161,18 @@ def view_w(name = 'Test', do_type = ''):
             else:
                 file_data = ''
         else:
+            curs.execute(db_change("select link from back where title = ? and type = 'include' limit 1"), [name])
+            doc_type = 'include' if curs.fetchall() else doc_type
+
+            curs.execute(db_change("select link from back where link = ? and type = 'redirect' limit 1"), [name])
+            doc_type = 'redirect' if curs.fetchall() else doc_type
+
             name_view = name
 
         end_data = '''
             <div id="opennamu_preview_area">
                 <textarea id="opennamu_editor_doc_name" style="display: none;">''' + html.escape(name) + '''</textarea>
-                <script>opennamu_view_w();</script>
+                <script>opennamu_view_w("''' + ('from' if do_type == 'from' else '') + '''");</script>
             </div>
         '''
 
@@ -185,27 +192,15 @@ def view_w(name = 'Test', do_type = ''):
             response_data = 404
 
             curs.execute(db_change('select data from other where name = "error_404"'))
-            sql_d = curs.fetchall()
-            if sql_d and sql_d[0][0] != '':
-                end_data = '<h2>' + load_lang('error') + '</h2><ul class="opennamu_ul"><li>' + sql_d[0][0] + '</li></ul>'
+            db_data = curs.fetchall()
+            if db_data and db_data[0][0] != '':
+                end_data = '<h2>' + load_lang('error') + '</h2><ul class="opennamu_ul"><li>' + db_data[0][0] + '</li></ul>'
             else:
                 end_data = '<h2>' + load_lang('error') + '</h2><ul class="opennamu_ul"><li>' + load_lang('decument_404_error') + '</li></ul>'
 
-            curs.execute(db_change('select ip, date, leng, send, id from history where title = ? and hide != "O" order by id + 0 desc limit 3'), [name])
-            sql_d = curs.fetchall()
-            if sql_d:
-                end_data += '<h2>' + load_lang('history') + '</h2><ul class="opennamu_ul">'
-                for i in sql_d:
-                    if re.search(r"\+", i[2]):
-                        leng = '<span style="color:green;">(' + i[2] + ')</span>'
-                    elif re.search(r"\-", i[2]):
-                        leng = '<span style="color:red;">(' + i[2] + ')</span>'
-                    else:
-                        leng = '<span style="color:gray;">(' + i[2] + ')</span>'
-
-                    end_data += '<li>' + i[1] + ' | r' + i[4] + ' | ' + ip_pas(i[0]) + ' | ' + leng + (' | ' + i[3] if i[3] != '' else '') + '</li>'
-
-                end_data += '<li><a href="/history/' + url_pas(name) + '">(...)</a></li></ul>'
+            curs.execute(db_change('select ip from history where title = ? limit 1'), [name])
+            db_data = curs.fetchall()
+            history_color = 1 if db_data else 0
         else:
             response_data = 200
 
@@ -219,7 +214,7 @@ def view_w(name = 'Test', do_type = ''):
 
         menu += [
             ['topic/' + url_pas(name), load_lang('discussion'), topic], 
-            ['history/' + url_pas(name), load_lang('history')], 
+            ['history/' + url_pas(name), load_lang('history'), history_color], 
             ['xref/' + url_pas(name), load_lang('backlink')], 
             ['acl/' + url_pas(name), load_lang('setting'), acl],
         ]
@@ -316,6 +311,10 @@ def view_w(name = 'Test', do_type = ''):
         body = curs.fetchall()
         div += body[0][0] if body else ''
 
+        curs.execute(db_change("select set_data from data_set where doc_name = ? and set_name = 'document_top'"), [name])
+        body = curs.fetchall()
+        div = (body[0][0] + div) if body else div
+
         if ip_or_user(ip) == 0:
             curs.execute(db_change("select data from user_set where id = ? and data = ?"), [ip, name])
             watch_list = 2 if curs.fetchall() else 1
@@ -323,6 +322,8 @@ def view_w(name = 'Test', do_type = ''):
         else:
             watch_list = 0
 
+        menu += [['doc_watch_list/1/' + url_pas(name), load_lang('watchlist')]]
+
         return easy_minify(flask.render_template(skin_check(),
             imp = [name_view, wiki_set(), wiki_custom(), wiki_css([sub, r_date, watch_list])],
             data = div,

BIN
route_go/bin/main.amd64.bin


BIN
route_go/bin/main.amd64.exe


BIN
route_go/bin/main.arm64.bin


BIN
route_go/bin/main.arm64.exe


+ 2 - 0
route_go/main.go

@@ -32,5 +32,7 @@ func main() {
 		route.Api_w_xref(call_arg[1:])
 	} else if call_arg[0] == "api_w_watch_list" {
 		route.Api_w_watch_list(call_arg[1:])
+	} else if call_arg[0] == "api_user_watch_list" {
+		route.Api_user_watch_list(call_arg[1:])
 	}
 }

+ 74 - 0
route_go/route/api_user_watch_list.go

@@ -0,0 +1,74 @@
+package route
+
+import (
+	"database/sql"
+	"encoding/json"
+	"fmt"
+	"opennamu/route/tool"
+	"strconv"
+)
+
+func Api_user_watch_list(call_arg []string) {
+	db_set := map[string]string{}
+	json.Unmarshal([]byte(call_arg[0]), &db_set)
+
+	other_set := map[string]string{}
+	json.Unmarshal([]byte(call_arg[1]), &other_set)
+
+	page, _ := strconv.Atoi(other_set["num"])
+	num := 0
+	if page*50 > 0 {
+		num = page*50 - 50
+	}
+
+	db := tool.DB_connect(db_set)
+	if db == nil {
+		return
+	}
+	defer db.Close()
+
+	ip := other_set["ip"]
+	name := other_set["name"]
+	if ip != name && tool.Get_admin_auth(db, db_set, ip) == "" {
+		fmt.Print("{}")
+		return
+	}
+
+	var stmt *sql.Stmt
+	var err error
+	if other_set["do_type"] == "star_doc" {
+		stmt, err = db.Prepare(tool.DB_change(db_set, "select data from user_set where name = 'star_doc' and id = ? limit ?, 50"))
+	} else {
+		stmt, err = db.Prepare(tool.DB_change(db_set, "select data from user_set where name = 'watchlist' and id = ? limit ?, 50"))
+	}
+	if err != nil {
+		return
+	}
+	defer stmt.Close()
+
+	rows, err := stmt.Query(name, num)
+	if err != nil {
+		return
+	}
+	defer rows.Close()
+
+	var data_list []string
+
+	for rows.Next() {
+		var title_data string
+
+		err := rows.Scan(&title_data)
+		if err != nil {
+			return
+		}
+
+		data_list = append(data_list, title_data)
+	}
+
+	if len(data_list) == 0 {
+		fmt.Print("{}")
+	} else {
+		json_data, _ := json.Marshal(data_list)
+		fmt.Print(string(json_data))
+	}
+}

+ 1 - 1
version.json

@@ -1,6 +1,6 @@
 {
     "beta" : {
-        "r_ver" : "v3.5.0-dev41",
+        "r_ver" : "v3.5.0-dev47",
         "c_ver" : "3500376",
         "s_ver" : "3500113"
     }

+ 18 - 78
views/main_css/js/func/func.js

@@ -1,83 +1,5 @@
 "use strict";
 
-// https://css-tricks.com/how-to-animate-the-details-element/
-class Accordion {
-    constructor(el) {
-        this.el = el;
-        this.summary = el.querySelector('summary');
-        this.content = el.querySelector('.opennamu_folding');
-    
-        this.animation = null;
-        this.isClosing = false;
-        this.isExpanding = false;
-        this.summary.addEventListener('click', (e) => this.onClick(e));
-    }
-  
-    onClick(e) {
-        e.preventDefault();
-        this.el.style.overflow = 'hidden';
-        if(this.isClosing || !this.el.open) {
-            this.open();
-        } else if(this.isExpanding || this.el.open) {
-            this.shrink();
-        }
-    }
-  
-    shrink() {
-        this.isClosing = true;
-        
-        const startHeight = `${this.el.offsetHeight}px`;
-        const endHeight = `${this.summary.offsetHeight}px`;
-        
-        if(this.animation) {
-            this.animation.cancel();
-        }
-        
-        this.animation = this.el.animate({
-            height: [startHeight, endHeight]
-        }, {
-            duration: 200,
-            easing: 'ease-out'
-        });
-        
-        this.animation.onfinish = () => this.onAnimationFinish(false);
-        this.animation.oncancel = () => this.isClosing = false;
-    }
-  
-    open() {
-        this.el.style.height = `${this.el.offsetHeight}px`;
-        this.el.open = true;
-        window.requestAnimationFrame(() => this.expand());
-    }
-  
-    expand() {
-        this.isExpanding = true;
-        const startHeight = `${this.el.offsetHeight}px`;
-        const endHeight = `${this.summary.offsetHeight + this.content.offsetHeight}px`;
-        
-        if(this.animation) {
-            this.animation.cancel();
-        }
-        
-        this.animation = this.el.animate({
-            height: [startHeight, endHeight]
-        }, {
-            duration: 200,
-            easing: 'ease-out'
-        });
-        this.animation.onfinish = () => this.onAnimationFinish(true);
-        this.animation.oncancel = () => this.isExpanding = false;
-    }
-  
-    onAnimationFinish(open) {
-        this.el.open = open;
-        this.animation = null;
-        this.isClosing = false;
-        this.isExpanding = false;
-        this.el.style.height = this.el.style.overflow = '';
-    }
-}
-
 function opennamu_do_id_check(data) {
     if(data.match(/\.|\:/)) {
         return 0;
@@ -86,6 +8,24 @@ function opennamu_do_id_check(data) {
     }
 }
 
+function opennamu_do_ip_render() {
+    let temp = {};
+    for(let for_a = 0; for_a < document.getElementsByClassName('opennamu_render_ip').length; for_a++) {
+        let ip = document.getElementsByClassName('opennamu_render_ip')[for_a].innerHTML.replace(/&amp;/g, '&');
+
+        if(temp[ip]) {
+            document.getElementsByClassName('opennamu_render_ip')[for_a].innerHTML = temp[ip];
+        } else {
+            fetch('/api/ip/' + opennamu_do_url_encode(ip)).then(function(res) {
+                return res.json();
+            }).then(function(data) {
+                document.getElementsByClassName('opennamu_render_ip')[for_a].innerHTML = data["data"];
+                temp[ip] = data["data"];
+            });
+        }
+    }
+}
+
 function opennamu_do_url_encode(data) {
     return encodeURIComponent(data);
 }

+ 78 - 0
views/main_css/js/route/render.js

@@ -1,5 +1,83 @@
 "use strict";
 
+// https://css-tricks.com/how-to-animate-the-details-element/
+class Accordion {
+    constructor(el) {
+        this.el = el;
+        this.summary = el.querySelector('summary');
+        this.content = el.querySelector('.opennamu_folding');
+    
+        this.animation = null;
+        this.isClosing = false;
+        this.isExpanding = false;
+        this.summary.addEventListener('click', (e) => this.onClick(e));
+    }
+  
+    onClick(e) {
+        e.preventDefault();
+        this.el.style.overflow = 'hidden';
+        if(this.isClosing || !this.el.open) {
+            this.open();
+        } else if(this.isExpanding || this.el.open) {
+            this.shrink();
+        }
+    }
+  
+    shrink() {
+        this.isClosing = true;
+        
+        const startHeight = `${this.el.offsetHeight}px`;
+        const endHeight = `${this.summary.offsetHeight}px`;
+        
+        if(this.animation) {
+            this.animation.cancel();
+        }
+        
+        this.animation = this.el.animate({
+            height: [startHeight, endHeight]
+        }, {
+            duration: 200,
+            easing: 'ease-out'
+        });
+        
+        this.animation.onfinish = () => this.onAnimationFinish(false);
+        this.animation.oncancel = () => this.isClosing = false;
+    }
+  
+    open() {
+        this.el.style.height = `${this.el.offsetHeight}px`;
+        this.el.open = true;
+        window.requestAnimationFrame(() => this.expand());
+    }
+  
+    expand() {
+        this.isExpanding = true;
+        const startHeight = `${this.el.offsetHeight}px`;
+        const endHeight = `${this.summary.offsetHeight + this.content.offsetHeight}px`;
+        
+        if(this.animation) {
+            this.animation.cancel();
+        }
+        
+        this.animation = this.el.animate({
+            height: [startHeight, endHeight]
+        }, {
+            duration: 200,
+            easing: 'ease-out'
+        });
+        this.animation.onfinish = () => this.onAnimationFinish(true);
+        this.animation.oncancel = () => this.isExpanding = false;
+    }
+  
+    onAnimationFinish(open) {
+        this.el.open = open;
+        this.animation = null;
+        this.isClosing = false;
+        this.isExpanding = false;
+        this.el.style.height = this.el.style.overflow = '';
+    }
+}
+
 function opennamu_heading_folding(data, element = '') {
     let fol = document.getElementById(data);
     if(fol.style.display === '' || fol.style.display === 'inline-block' || fol.style.display === 'block') {

+ 2 - 2
views/main_css/js/route/view.js

@@ -48,7 +48,7 @@ function opennamu_view_w_raw_preview() {
     opennamu_do_render('opennamu_preview_area', data, name);
 }
 
-function opennamu_view_w() {
+function opennamu_view_w(do_type = '') {
     let name = "test";
     if(document.getElementById('opennamu_editor_doc_name')) {
         name = document.getElementById('opennamu_editor_doc_name').innerHTML.replace(/&amp;/g, '&');
@@ -58,7 +58,7 @@ function opennamu_view_w() {
         return res.json();
     }).then(function(data) {
         if(data["data"]) {
-            opennamu_do_render('opennamu_preview_area', data["data"], name);
+            opennamu_do_render('opennamu_preview_area', data["data"], name, do_type);
         }
     });
 }