Changeset 304 in main


Ignore:
Timestamp:
09/21/11 08:53:49 (8 years ago)
Author:
pcosquer
Message:

navigate: make it possible to add a part to the main part by dnd
still a lot more to do

Location:
trunk/openPLM
Files:
1 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/openPLM/media/css/openplm.css

    r298 r304  
    543543} 
    544544 
     545div.drop_active{ 
     546    border: 1px solid red; 
     547} 
     548 
     549div.drop_hover { 
     550    background: rgba(200,100,100,0.5); 
     551} 
     552 
     553 
    545554img.node_thumbnails, img.node_show_docs { 
    546555    position:absolute; 
  • trunk/openPLM/media/js/navigate.js

    r301 r304  
    6767 
    6868 
     69function show_add_child(part, form_child){ 
     70        var id = part.attr("id").split(":"); 
     71    var type = id.slice(-2, -1); 
     72    var id = id.slice(-1); 
     73    $.get("/ajax/add_child/" + id + "/", 
     74        form_child.serialize(), 
     75        function (data){ 
     76            $("#navAddForm").dialog("option", "buttons", { 
     77                Ok: function() { 
     78                    $.post("/ajax/add_child/"+id+"/", 
     79                        $("#navAddForm>form").serialize(), 
     80                        function (result){ 
     81                            if (result.result == "ok"){ 
     82                                $("#navAddForm").dialog("close"); 
     83                                location.reload(); 
     84                            } 
     85                            else if (result.error == "invalid form") { 
     86                                $("#navAddForm>form>table").html(result.form); 
     87 
     88                            } 
     89                        }); 
     90                }, 
     91                Cancel: function() { 
     92                    $(this).dialog("close"); 
     93                } 
     94                 
     95            }); 
     96            $("#navAddForm>form>table").html(data.form); 
     97            $("#navAddForm").dialog("open"); 
     98        } 
     99    ); 
     100} 
     101 
    69102function init(){ 
    70103        $("div.node").mouseenter( 
    71104        function () { 
    72             $(this).find(".node_thumbnails").show(); 
    73             $(this).find(".node_show_docs").show(); 
     105            if (! ($(this).hasClass("drop_active") || $(this).hasClass("drop_hover"))){ 
     106                $(this).find(".node_thumbnails").show(); 
     107                $(this).find(".node_show_docs").show(); 
     108            } 
    74109        });  
    75110        $("div.node").mouseleave( 
     
    95130        $(".node_thumbnails").hoverIntent(config); 
    96131 
     132        // add stuff 
     133        // TODO : documents, check if selected part can be added 
     134        $("div.main_node").droppable({ 
     135                        accept: "tr.Content", 
     136                        activeClass: "drop_active", 
     137                        hoverClass: "drop_hover", 
     138                        drop: function( event, ui ) { 
     139                show_add_child($(this), $("form", ui.draggable)); 
     140                        } 
     141                }); 
     142 
    97143} 
    98144 
     
    101147        // Supprime la scrollbar en JS 
    102148        $('#Navigate').css('overflow', 'hidden'); 
    103  
    104         // Insert les images de navigation 
    105         //    $('#Navigate') 
    106         //    .append('<div id="imgManagement"><span class="imgManagement" id="topControl"></span><span class="imgManagement" id="leftControl"></span><span class="imgManagement" id="rightControl"></span><span class="imgManagement" id="bottomControl"></span></div>'); 
    107149 
    108150        // crée un écouteur pour l'évènement de type clic sur les div qui ont l' id #rightControl 
     
    194236                } ); 
    195237 
     238        // add on drag and drop 
     239        $("tr.Content").add("tr.Content2").css("z-index", "99"); 
     240        $("tr.Content").add("tr.Content2").draggable({ helper: 'clone' }); 
     241        $("#navAddForm").dialog({ 
     242                autoOpen: false, 
     243                        height: 300, 
     244                        width: 350, 
     245                        modal: true, 
     246                        close: function() { 
     247                        } 
     248                }); 
     249 
    196250        init(); 
    197251}); 
  • trunk/openPLM/plmapp/api.py

    r303 r304  
    3030 
    3131import functools 
    32 import traceback 
    33 import sys 
    3432 
    3533import django.forms 
    36 from django.shortcuts import get_object_or_404 
    37 from django.utils import simplejson 
    38 from django.core.mail import mail_admins 
    39 from django.utils.translation import ugettext as _ 
    4034from django.contrib.auth.decorators import user_passes_test 
    4135from django.contrib.auth import authenticate, login 
    42 from django.http import HttpResponse, HttpResponseForbidden 
     36from django.http import HttpResponseForbidden 
    4337from django.contrib.csrf.middleware import csrf_exempt 
    4438 
     
    4741import openPLM.plmapp.forms as forms 
    4842from openPLM.plmapp.utils import get_next_revision 
     43from openPLM.plmapp.base_views import json_view, get_obj_by_id 
    4944 
    5045#: Version of the API (value: ``'1.0'``) 
     
    5449                                      login_url="/api/needlogin/") 
    5550 
    56 def json_view(func): 
    57     """ 
    58     Decorator which converts the result from *func* into a json response. 
    59      
    60     The result from *func* must be serializable by :mod:`django.utils.simple_json` 
    61      
    62     This decorator automatically adds a ``result`` field to the response if it 
    63     was not present. Its value is ``'ok'`` if no exception was raised, and else, 
    64     it is ``'error'``. In that case, a field ``'error'`` is had with a short 
    65     message describing the exception. 
    66     """ 
    67     @functools.wraps(func) 
    68     def wrap(request, *a, **kw): 
    69         response = None 
    70         try: 
    71             response = dict(func(request, *a, **kw)) 
    72             if 'result' not in response: 
    73                 response['result'] = 'ok' 
    74         except KeyboardInterrupt: 
    75             # Allow keyboard interrupts through for debugging. 
    76             raise 
    77         except Exception, e: 
    78             #Mail the admins with the error 
    79             exc_info = sys.exc_info() 
    80             subject = 'JSON view error: %s' % request.path 
    81             try: 
    82                 request_repr = repr(request) 
    83             except: 
    84                 request_repr = 'Request repr() unavailable' 
    85             message = 'Traceback:\n%s\n\nRequest:\n%s' % ( 
    86                 '\n'.join(traceback.format_exception(*exc_info)), 
    87                 request_repr, 
    88                 ) 
    89             mail_admins(subject, message, fail_silently=True) 
    90             #Come what may, we're returning JSON. 
    91             msg = _('Internal error') + ': ' + str(e) 
    92             response = {'result' : 'error', 'error' : msg} 
    93         response["api_version"] = API_VERSION 
    94         json = simplejson.dumps(response) 
    95         return HttpResponse(json, mimetype='application/json') 
    96     return wrap 
     51@json_view 
     52def need_login(request): 
     53    """ Helper function for :func:`api_login_required` """ 
     54    return {'result' : 'error', 'error' : 'user must be login'} 
    9755 
    9856def login_json(func): 
     
    10563    """ 
    10664    
    107     json_func = json_view(func) 
     65    json_func = json_view(func, API_VERSION) 
    10866    @api_login_required 
    10967    @csrf_exempt 
     
    11573    return wrapper 
    11674 
    117  
    118 def get_obj_by_id(obj_id, user): 
    119     u""" 
    120     Returns an adequate controller for the object identify by *obj_id*. 
    121     The returned controller is instanciate with *user* as the user 
    122     who modify the object. 
    123  
    124     :param obj_id: id of a :class:`.PLMObject` 
    125     :param user: a :class:`.django.contrib.auth.models.User` 
    126     :return: a subinstance of a :class:`.PLMObjectController` 
    127     """ 
    128  
    129     obj = get_object_or_404(models.PLMObject, id=obj_id) 
    130     obj = models.get_all_plmobjects()[obj.type].objects.get(id=obj_id) 
    131     return get_controller(obj.type)(obj, user) 
    132  
    133 def object_to_dict(plmobject): 
    134     """ 
    135     Returns a dictionary representing *plmobject*. The returned dictionary 
    136     respects the format described in :ref`http-api-object` 
    137     """ 
    138     return dict(id=plmobject.id, name=plmobject.name, type=plmobject.type, 
    139                 revision=plmobject.revision, reference=plmobject.reference) 
    140  
    141 @json_view 
    142 def need_login(request): 
    143     """ Helper function for :func:`api_login_required` """ 
    144     return {'result' : 'error', 'error' : 'user must be login'} 
    14575 
    14676@login_json 
  • trunk/openPLM/plmapp/forms.py

    r303 r304  
    209209    order = forms.IntegerField() 
    210210 
     211 
    211212class DisplayChildrenForm(forms.Form): 
    212213    LEVELS = (("all", "All levels",), 
  • trunk/openPLM/plmapp/navigate.py

    r300 r304  
    263263        node = self.graph.get_node(id_) 
    264264        self._set_node_attributes(self.object, id_) 
     265        self.main_node = node.attr["id"] 
    265266        color = node.attr["color"] 
    266267        node.attr.update(color="#444444", fillcolor=color, shape="box", root="true") 
     
    304305            node.attr["label"] = encode(obj.username) 
    305306        node.attr["label"] += "\\n" + encode(extra_label) 
    306         node.attr["id"] = obj_id or obj.id 
     307        t = type_.__name__.replace("Controller", "") 
     308        node.attr["id"] = ":".join((str(obj_id or obj.id), t, str(obj.id))) 
    307309 
    308310    def convert_map(self, map_string): 
     
    317319            id_ = "Nav-%s" % area.get("id") 
    318320            div = ET.Element("div", id=id_, style=style) 
    319             div.set("class", "node") 
     321            div.set("class", "node" + " main_node" * (self.main_node == area.get("id"))) 
    320322            url = area.get("title") 
    321323            if url.startswith("/ajax/thumbnails/"): 
  • trunk/openPLM/plmapp/views.py

    r303 r304  
    5353 
    5454from django.conf import settings 
    55 from django.shortcuts import render_to_response, get_object_or_404 
     55from django.shortcuts import render_to_response 
    5656from django.http import HttpResponseRedirect, HttpResponse,\ 
    5757                        HttpResponsePermanentRedirect, HttpResponseForbidden, \ 
     
    7373from openPLM.plmapp.forms import * 
    7474from openPLM.plmapp.navigate import NavigationGraph 
     75from openPLM.plmapp.base_views import get_obj, get_obj_by_id, json_view 
    7576 
    7677 
     
    105106 
    106107 
    107 ########################################################################################## 
    108 def get_obj(obj_type, obj_ref, obj_revi, user): 
    109     """ 
    110     Get type, reference and revision of an object and return the related controller 
    111      
    112     :param obj_type: :attr:`.PLMObject.type` 
    113     :type obj_type: str 
    114     :param obj_ref: :attr:`.PLMObject.reference` 
    115     :type obj_ref: str 
    116     :param obj_revi: :attr:`.PLMObject.revision` 
    117     :type obj_revi: str 
    118     :return: a :class:`PLMObjectController` or a :class:`UserController` 
    119     """ 
    120     if obj_type=='User': 
    121         obj = get_object_or_404(User, 
    122                                 username=obj_ref) 
    123         controller_cls = UserController 
    124     else: 
    125         obj = get_object_or_404(models.PLMObject, type=obj_type, 
    126                                 reference=obj_ref, 
    127                                 revision=obj_revi) 
    128         # guess what kind of PLMObject (Part, Document) obj is 
    129         cls = models.PLMObject 
    130         find = True 
    131         while find: 
    132             find = False 
    133             for c in cls.__subclasses__(): 
    134                 if hasattr(obj, c.__name__.lower()): 
    135                     cls  = c 
    136                     obj = getattr(obj, c.__name__.lower()) 
    137                     find = True 
    138         controller_cls = get_controller(obj_type) 
    139     return controller_cls(obj, user) 
    140  
    141 ########################################################################################## 
    142108def init_context_dict(init_type_, init_reference, init_revision): 
    143109    """ 
     
    15011467 
    15021468@login_required 
     1469@json_view 
    15031470def ajax_thumbnails(request, obj_type, obj_ref, obj_revi): 
    15041471    """ 
     
    15221489            img = "/media/img/image-missing.png" 
    15231490        files.append((f.filename, "/file/%d/" % f.id, img)) 
    1524     json = JSONEncoder().encode(dict(files=files, doc=doc)) 
    1525     return HttpResponse(json, mimetype='application/json') 
     1491    return dict(files=files, doc=doc) 
    15261492 
    15271493 
    15281494@login_required 
     1495@json_view 
    15291496def ajax_navigate(request, obj_type, obj_ref, obj_revi): 
    15301497    context = get_navigate_data(request, obj_type, obj_ref, obj_revi) 
     1498    data = { 
     1499            "img" : context["picture_path"], 
     1500            "divs" : context["map_areas"], 
     1501            "left" : context["x_img_position"], 
     1502            "top" : context["y_img_position"], 
     1503            "form" : context["filter_object_form"].as_ul(), 
     1504            } 
     1505    return data 
     1506 
     1507@login_required 
     1508@json_view 
     1509def ajax_add_child(request, part_id): 
     1510    part = get_obj_by_id(part_id, request.user) 
    15311511    data = {} 
    1532     data["img"] = context["picture_path"] 
    1533     data["divs"] = context["map_areas"] 
    1534     data["left"] = context["x_img_position"] 
    1535     data["top"] = context["y_img_position"] 
    1536     data["form"] = context["filter_object_form"].as_ul() 
    1537     json = JSONEncoder().encode(data) 
    1538     return HttpResponse(json, mimetype='application/json') 
    1539  
     1512    if request.GET: 
     1513        form = AddChildForm(initial=request.GET) 
     1514    else: 
     1515        form = AddChildForm(request.POST) 
     1516        if form.is_valid(): 
     1517            child = get_obj(form.cleaned_data["type"], 
     1518                                form.cleaned_data["reference"], 
     1519                                form.cleaned_data["revision"], 
     1520                                request.user) 
     1521            part.add_child(child, form.cleaned_data["quantity"],  
     1522                           form.cleaned_data["order"]) 
     1523            return {"result" : "ok"} 
     1524        else: 
     1525            data["result"] = "error" 
     1526            data["error"] = "invalid form" 
     1527    for field in ("type", "reference", "revision"): 
     1528        form.fields[field].widget.attrs['readonly'] = 'on'  
     1529    data.update({ 
     1530            "parent" : { 
     1531                "id" : part.id, 
     1532                "type" : part.type, 
     1533                "reference" : part.reference, 
     1534                "revision" : part.revision, 
     1535                }, 
     1536            "form" : form.as_table() 
     1537           }) 
     1538    return data 
     1539 
  • trunk/openPLM/plmapp/widgets.py

    r285 r304  
    4646                }) 
    4747 
     48 
  • trunk/openPLM/templates/DisplayHomePage.htm

    r303 r304  
    8585                            </td> 
    8686                            {% endif %} 
    87                             {% endif %} 
    88                             {% if link_creation %} 
     87                        {% endif %} 
    8988 
    90                                             <form method="post" action="." enctype="multipart/form-data"> 
     89                                        <form method="post" action="." enctype="multipart/form-data"> 
    9190                                {% if object.username %} 
    9291                        <input type="hidden" name="type" value="User"/> 
     
    9998 
    10099                                {% endif %} 
     100                            {% if link_creation %} 
    101101 
    102102                                <td class="Content"> 
    103103                            <input type="submit" value="{% trans "ADD" %}"/> 
    104104                        </td> 
    105                     </form> 
    106105                        {% endif %} 
    107                             </td> 
     106                        </form> 
    108107                    </tr> 
    109108            {% empty %} 
  • trunk/openPLM/templates/Navigate.htm

    r299 r304  
    1313{% block content %} 
    1414    <div id="Navigate"> 
     15        <div id="navAddForm"> 
     16            <form method="POST" action=""> 
     17                <table> 
     18                    <tbody/> 
     19                </table> 
     20            </form> 
     21        </div> 
    1522    <div id="navThumbnails"> 
    1623         
  • trunk/openPLM/urls.py

    r299 r304  
    6868    (r'ajax/thumbnails/(?P<obj_type>\w+)/(?P<obj_ref>%(x)s)/(?P<obj_revi>%(x)s)/?$' % {'x' : r'[^/?#\t\r\v\f]+'}, ajax_thumbnails), 
    6969    (r'ajax/navigate/(?P<obj_type>\w+)/(?P<obj_ref>%(x)s)/(?P<obj_revi>%(x)s)/?$' % {'x' : r'[^/?#\t\r\v\f]+'}, ajax_navigate), 
     70    (r'ajax/add_child/(?P<part_id>\d+)/?', ajax_add_child), 
    7071 
    7172    (object_url + r'$', display_object), 
Note: See TracChangeset for help on using the changeset viewer.