Anonymous avatar Anonymous committed d1d49da

new window to insert link
now you can enter better title.

Comments (0)

Files changed (9)

 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+
+from werkzeug.utils import url_quote_plus
 from pygments.lexers import get_all_lexers, get_lexer_for_filename
 from pygments.styles import get_all_styles
 
+
 from couchdb.client import ResourceNotFound
 from couchit.models import Site, Page
 from couchit.utils import utf8, make_hash
     Rule('/site/export.<feedtype>', endpoint='site_export'),
     Rule('/site/login', endpoint='site_login'),
     Rule('/site/logout', endpoint='site_logout'),
-    Rule('/<pagename>/revisions.<feedtype>', endpoint='revisions_feed'),
-    Rule('/<pagename>/revision/<nb_revision>', endpoint='revision_page'),
-    Rule('/<pagename>/history', endpoint='history_page'),
-    Rule('/<pagename>/edit', endpoint='edit_page'),
-    Rule('/<pagename>/delete', endpoint='delete_page'),
-    Rule('/<pagename>/diff', endpoint='diff_page'),
-    Rule('/<pagename>/', endpoint='show_page', strict_slashes=False),
-    Rule('/<pagename>', endpoint='show_page', strict_slashes=False)
+    Rule('/<path:pagename>/revisions.<feedtype>', endpoint='revisions_feed'),
+    Rule('/<path:pagename>/revision/<nb_revision>', endpoint='revision_page'),
+    Rule('/<path:pagename>/history', endpoint='history_page'),
+    Rule('/<path:pagename>/edit', endpoint='edit_page'),
+    Rule('/<path:pagename>/delete', endpoint='delete_page'),
+    Rule('/<path:pagename>/diff', endpoint='diff_page'),
+    Rule('/<path:pagename>/', endpoint='show_page', strict_slashes=False),
+    Rule('/<path:pagename>', endpoint='show_page', strict_slashes=False)
     
    
 ])
 
 FORBIDDEN_CNAME = ['mail', 'www', 'blog', 'news', 'media', 'upload', 'files', 'store']
 
-re_page = re.compile(r"^[\"\'\- \w]+$", re.U)
+re_page = re.compile(r"^[\"\'\-\/ \w]+$", re.U)
 re_address = re.compile(r'^[-_\w]+$')
 
 
     return decorated
     
     
+def valid_page(f):
+    def decorated(request, **kwargs):
+        if 'pagename' in kwargs:
+            pagename = kwargs['pagename'] 
+            if not re_page.match(pagename) and pagename is not None:
+                raise NotFound
+        return f(request, **kwargs)
+    return decorated
+        
+    
 def not_found(request):
     return render_response("not_found.html")
 
+
 def home(request, cname=None, alias=None):
     def randomid():
         return str(uuid.uuid4()).replace('-','')
                 b1=b1, b2=b2, spamid=spamid, spaminput=spaminput, createid=createid)
   
   
-  
+@valid_page
 def show_page(request=None, pagename=None):
     if pagename is None:
         pagename ='home'
             pagename=page.title.replace(' ', '_'),
             redirect_from=pagename))
     
-    if not page or page.id is None or not re_page.match(pagename):
+    if not page or page.id is None:
         if pagename.lower() in FORBIDDEN_PAGES:
             redirect_url = "%s?error=%s" % (
                 url_for('show_page', pagename='home'),
     return response
 
 @can_edit
+@valid_page
 def edit_page(request, pagename=None):
     if pagename is None:
         pagename ='Home'
 
 @can_edit
 @login_required
+@valid_page
 def delete_page(request, pagename):
     if pagename == 'Home': #security reason
         return redirect(url_for('show_page', pagename='Home'))
         redirect_url = '/'
     return redirect(redirect_url)
     
-
+@valid_page
 def history_page(request=None, pagename=None):
     if pagename is None:
         pagename ='Home'
 
     return render_response('page/history.html', page=page, pages=pages, revisions=revisions)
     
-
+@valid_page
 def revision_page(request=None, pagename=None, nb_revision=None):
     if pagename is None:
         pagename ='Home'
     pages = all_pages(local.db, request.site.id)
     
     return render_response('page/show.html', page=revision, pages=pages)
-   
+
+@valid_page  
 def diff_page(request=None, pagename=None):
     if pagename is None:
         pagename ='Home'
     rev2=rev2, revisions=all_revisions)
 
     
-  
+@valid_page  
 def revisions_feed(request=None, pagename=None, feedtype="atom"):
     if pagename is None:
         pagename ='Home'

static/css/src/layout.css

 aside.hidden { display: none;}
 
 
-
-
+.hidden {
+    display: none;
+}
 header h1,
 header h2 { padding:0px;}
 
     cursor: pointer;
     cursor: hand;  
 }
-#snippet_window form table {
+
+#link_window textarea {
+    width: 350px;
+}
+
+#snippet_window form table,
+#link_window form table {
     width: 100%;
     margin: 5px 0 5px 0;
 }
-#snippet_window th, td {
+#snippet_window th, 
+#snippet_window td,
+#link_window th, 
+#link_window td {
     padding: 5px 10px 5px 10px;
     vertical-align: top;
 }
 
+tr.rlink_type {
+    border-bottom: 1px solid;
+}
+
+#link_window input[type="text"] {
+    width: 350px;
+}
 #snippet_window textarea {
     width: 450px;
     height: 200px;
     
 }
 
-#snippet_window p {
+#snippet_window p,
+#link_window p {
     line-height: 15px;
     vertical-align: middle;
     margin-top: 5px;
     
 }
 
-#snippet_window input[type="submit"] {
+#snippet_window input[type="submit"],
+#link_window {
     border: 1px solid;
 }
 

static/css/src/slate.css

     color: #bbb;
 }
 
+tr.rlink_type {
+    border-color: #fff;
+}
+
 input, textarea {
     border-color: #C6C6C6 #EFEFEF #EFEFEF #C6C6C6;
 }

static/js/src/application.js

     
     submit: function() { 
         var title = $("title");
-        //a-zA-Z0-9_\\u00A1-\\uFFFF
-        if (!title.value.match(/^['\-\" \w\u00A1-\uFFFF]+$/i) || FORBIDDEN_PAGES.indexOf(title.value) >= 0) {
+        if (!title.value.match(/^['\-\"\/ \w\u00A1-\uFFFF]+$/i) || FORBIDDEN_PAGES.indexOf(title.value) >= 0) {
             alert("Page title invalid");
             return false;
         }
         
         var slug = title.value.replace(/ /g, "_");
-        document.location.href = Site.url + "/" +  slug + "#pedit";
+        url = Site.url + "/" +  slug + "#pedit";
+        
+        window.location.href = url;
+        this.Form.addClassName("hidden");
+        this.doCreate.removeClassName("hidden");
     },
 });
 

static/js/src/page.js

 var PageUI = Class.create({
     initialize: function() {
+        
+        this.firstload = true;
         var self = this;
         this.Sidebar = $('sidebar');
         this.Page = $('page');
         this.textarea.observe('change',self.converter_callback);
         
         this.snippet_window = new Control.Window($('snippet_window'), {
-            resizable: true,
+            resizable: false,
             draggable: $('snippet_window_title'),
             closeOnClick: $('snippet_window_close')
         });  
         
+        this.link_window = new Control.Window($('link_window'), {
+            draggable: $('link_window_title'),
+            closeOnClick: $('link_window_close')
+        });
+        
+        this.link_types_hide = {
+            'url': 'page',
+            'page': 'url'
+        }
+        
         this.build_toolbar();
         this.init();
         
             $('content').setStyle({'height': new_height + 'px'});
         }
         
+       
+        
         $('cancelEdit').observe('click', function(e) {
             Event.stop(e);
             self.tabs.setActiveTab("pview");
                 if (!y) {
                     return false;
                 }
-                document.location.href=this.href;
+                window.location.href=this.href;
             }, false);
             
         this._renamingPage = false;
               id: 'markdown_bold_button'  
           });  
 
-          this.toolbar.addButton('Link',function(){  
-              var selection = this.getSelection();  
+          this.toolbar.addButton('Link',function(){
+              var selection = this.getSelection();
+              self.link_window.open();
+              $('link_from_url').hide();
+              $("cancelLink").observe("click", function(e) {
+                  Event.stop(e);
+                  self.link_window.close();
+                  return false;
+              });
+              
+              $('link_type').observe('change', function(e) {
+                  var selected = this.getValue();
+                  
+                  $('link_from_'+ selected).show();
+                  $('link_from_'+self.link_types_hide[selected]).hide();
+                  
+              }, false);
+              
+              var tb = this;
+              $("slink").observe('click', function(e) {
+                  Event.stop(e);
+                  var link_type = $('link_type').getValue();
+                  var link_text = $('link_label').getValue();
+                  if (link_type == "page") {
+                      tb.replaceSelection('[' + (link_text == '' ? 'Link Text' : link_text) + '](' + $('link_page').getValue() + ')');
+                  } else {
+                      var url = $('link_url').getValue();
+;                     tb.replaceSelection('[' + (link_text == '' ? 'Link Text' : link_text) + '](' + (url == '' ? 'http://link_url/' : url).replace(/^(?!(f|ht)tps?:\/\/)/,'http://') + ')');
+                  }
+                  self.link_window.close();
+                    return false;
+              }, false);
+              
+              /*
               var response = prompt('Enter Link URL','');  
               if(response == null)  
-                  return;  
+                  return; 
               this.replaceSelection('[' + (selection == '' ? 'Link Text' : selection) + '](' + (response == '' ? 'http://link_url/' : response).replace(/^(?!(f|ht)tps?:\/\/)/,'http://') + ')');  
+                */
           },{  
               id: 'markdown_link_button'  
           });  
             'type': 'text',
             'id': 'new_title',
             'name': 'new_title',
+            'maxlength': '60',
             'value': $('page_title').innerHTML
         });
         var old_title = new Element('input', {

templates/page/show.html

 {% block footer %}
 
 {% if can_edit %}
+<div id="link_window" title="Enter Link Url" class="window">
+    <div id="link_window_close" class="close"></div>
+    <div id="link_window_title" class="window_title">Enter Link Url</div>
+    <form name="flink" id="flink">
+        <table>
+             <tr class="rlink_type">
+                    <th><label for="link_type">Link type:</label></th>
+                    <td>
+                        <select id="link_type" name="link_type">
+                            <option value="page" selected="selected">Page</option>
+                            <option value="url">URL</option>
+                        </select>
+                    </td>
+            </tr>
+            <tr>
+                <th><label for="link_label">Link text:</label></th>
+                <td><input type="text" name="link_label" id="link_label" value="" /></td>
+            </tr>
+            <tr id="link_from_page">
+                <th><label for="link_page">Page:</label></th>
+                <td>
+                    <select id="link_page" name="link_page">
+                        {% for p in pages %}
+                        <option  value="{{ url_for('show_page', pagename=p.title|replace(" ", "_"))  }}">{{ p.title }}</option>
+                        
+                        {% endfor %}
+                    </select>
+                </td>
+            </tr>
+            <tr id="link_from_url">
+                <th><label for="link_url">Url:</label></th>
+                <td><textarea id="link_url" name="link_url" cols="40" rows="2"></textarea></td>
+            </tr>
+        </table>
+         <p><input type="submit" id="slink" name="slink" value="Insert link" /><input type="submit" id="cancelLink" name="cancelLink" value="Cancel" /></p>
+    </form>
+</div>
+    
 <div id="snippet_window" title="insert a snipet" class="window">
     <div id="snippet_window_close" class="close"></div>
     <div id="snippet_window_title" class="window_title">Insert a snippet</div>

templates/sidebar.html

 <div id="createPage">
     <a href="#" id="doCreate">Create new page</a>
     <form id="fnewpage" name="fnewpage" method="get">
-        <p><input type="text" name="title" id="title" value="" maxlength="40"/></p>
+        <p><input type="text" name="title" id="title" value="" maxlength="60"/></p>
         <p><input type="submit" name="screate" id="screate" value="Create" /> or <a href="#" class="cancelCreate">Cancel</a></p>
     </form>
 </div>
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.