# HG changeset patch # User Laure Bourgois # Date 1238678515 -7200 # Node ID 9db3648c476d6d261887b85f0ab2352d2fb99c71 # Parent 25480a710422e3b4338f1366a871d683a675c6f9# Parent 76de1c3aaef3368f00d7a5b33bc41ba30d329634 merge diff -r 25480a710422 -r 9db3648c476d doc/book/en/A020-tutorial.en.txt --- a/doc/book/en/A020-tutorial.en.txt Thu Apr 02 15:21:00 2009 +0200 +++ b/doc/book/en/A020-tutorial.en.txt Thu Apr 02 15:21:55 2009 +0200 @@ -20,6 +20,7 @@ This tutorial will show how to create a `cube` and how to use it as an application to run an `instance`. +.. include:: Z013-blog-less-ten-minutes.en.txt .. include:: A02a-create-cube.en.txt .. include:: A02b-components.en.txt .. include:: A02c-maintemplate.en.txt diff -r 25480a710422 -r 9db3648c476d doc/book/en/B0010-define-schema.en.txt --- a/doc/book/en/B0010-define-schema.en.txt Thu Apr 02 15:21:00 2009 +0200 +++ b/doc/book/en/B0010-define-schema.en.txt Thu Apr 02 15:21:55 2009 +0200 @@ -1,10 +1,10 @@ .. -*- coding: utf-8 -*- -Data model definition (*schema*) -================================ +Data model definition: the *schema* +=================================== -The schema is the core piece of a `CubicWeb` application as it defines -the data model handled. It is based on entity types that are either already +The **schema** is the core piece of a `CubicWeb` application as it defines +the handled data model. It is based on entity types that are either already defined in the `CubicWeb` standard library; or more specific types, that `CubicWeb` expects to find in one or more Python files under the directory `schema`. diff -r 25480a710422 -r 9db3648c476d doc/book/en/B0011-schema-stdlib.en.txt --- a/doc/book/en/B0011-schema-stdlib.en.txt Thu Apr 02 15:21:00 2009 +0200 +++ b/doc/book/en/B0011-schema-stdlib.en.txt Thu Apr 02 15:21:55 2009 +0200 @@ -10,7 +10,7 @@ System schemas `````````````` -The system entities available are: +The available system entities are: * `EUser`, system users * `EGroup`, users groups @@ -34,7 +34,7 @@ (The first 'E' in some of the names is the first letter of 'Erudi', `CubicWeb`'s old name; it might be changed/removed some day.) -Cubes available +Available cubes ``````````````` An application is based on several basic cubes. In the set of available diff -r 25480a710422 -r 9db3648c476d doc/book/en/B0012-schema-definition.en.txt --- a/doc/book/en/B0012-schema-definition.en.txt Thu Apr 02 15:21:00 2009 +0200 +++ b/doc/book/en/B0012-schema-definition.en.txt Thu Apr 02 15:21:55 2009 +0200 @@ -148,8 +148,8 @@ not prevent another entity to be selected. -Relation definition -------------------- +Definition of relations +----------------------- XXX add note about defining relation type / definition @@ -221,8 +221,8 @@ Permissions definition `````````````````````` -Define permissions is set through to the attribute `permissions` of entities and -relations types. It defines a dictionnary where the keys are the access types +Setting permissions is done with the attribute `permissions` of entities and +relation types. It defines a dictionnary where the keys are the access types (action), and the values are the authorized groups or expressions. For an entity type, the possible actions are `read`, `add`, `update` and @@ -377,9 +377,9 @@ Updating your application with your new schema `````````````````````````````````````````````` -If you modified your schema, the update is not automatic; this is -indeed in general not a good idea. -Instead, we call a shell on your application, which is a +If you modified your schema, the update is not automatic; indeed, this is +in general not a good idea. +Instead, you call a shell on your application, which is a an interactive python shell, with an appropriate cubicweb environment :: diff -r 25480a710422 -r 9db3648c476d doc/book/en/B0020-define-workflows.en.txt --- a/doc/book/en/B0020-define-workflows.en.txt Thu Apr 02 15:21:00 2009 +0200 +++ b/doc/book/en/B0020-define-workflows.en.txt Thu Apr 02 15:21:55 2009 +0200 @@ -5,43 +5,22 @@ Workflow definition =================== +[TODO : All this is too obscure and often not very understandable...] + General ------- -A workflow can be defined in a `CubicWeb` application thanks to the system -entities ``State`` and ``Transition``. Those are defined within all -`CubicWeb` application and can be set-up through the main administrator interface. - -Once your schema is defined, you can start creating the set of states and -the required transitions for your applications entities. - -You first need to define the states and then the transitions between those -to complete your workflow. - -A ``State`` defines the status of an entity. While creating a new state, -you will be first given the option to select the entity type the state -can be applied to. By choosing ``Apply``, a new section will be displayed -in the editing screen to enable you to add relation to the state you are -creating. - -A ``Transition`` is also based on an entity type it can be applied to. -By choosing ``Apply``, a new section will be displayed in the editing -screen to enable you to add relation to the transition you are -creating. - -At the transition level you will also define the group of user which can -aplly this transition to an object. - +[XXX define what a "Workflow" is: states, transitions, transition graph ] Example of a simple workflow ---------------------------- -Please see the tutorial to view and example of a simple workflow. +Please see the tutorial to view an example of a simple workflow. [Create a simple workflow for BlogDemo, to have a moderator approve new blog -entry to be published. This implies, specify a dedicated group of blog -moderator as well as hide the view of a blog entry to the user until +entry to be published. This implies specifying a dedicated group of blog +moderator as well as hiding the view of a blog entry to the user until it reaches the state published] Set-up a workflow @@ -49,31 +28,24 @@ We want to create a workflow to control the quality of the BlogEntry submitted on your application. When a BlogEntry is created by a user -its state should be `submitted`. To be visible to all, it needs to -be in the state `published`. To move from `submitted` to `published` -we need a transition that we can name `approve_blogentry`. - -We do not want every user to be allowed to change the state of a -BlogEntry. We need to define a group of user, `moderators`, and -this group will have appropriate permissions to approve BlogEntry -to be published and visible to all. +its state should be `submitted`. To be visible to all, it has to +be in the state `published`. To move it from `submitted` to `published`, +we need a transition that we can call `approve_blogentry`. -There are two ways to create a workflow, form the user interface, -and also by defining it in ``migration/postcreate.py``. +A BlogEntry state should not be modifiable by every user. +So we have to define a group of users, `moderators`, and +this group will have appropriate permissions to publish a BlogEntry. + +There are two ways to create a workflow: from the user interface, +or by defining it in ``migration/postcreate.py``. This script is executed each time a new ``cubicweb-ctl db-init`` is done. -If you create the states and transitions through the user interface -this means that next time you will need to initialize the database -you will have to re-create all the entities. -We strongly recommand you create the workflow in ``migration\postcreate.py`` -and we will now show you how. -The user interface would only be a reference for you to view the states -and transitions but is not the appropriate interface to define your -application workflow. +We strongly recommand to create the workflow in ``migration/postcreate.py`` +and we will now show you how. Read `Under the hood`_ to understand why. Update the schema ~~~~~~~~~~~~~~~~~ -To enable a BlogEntry to have a State, we have to define a relation -``in_state`` in the schema of BlogEntry. Please do as follows, add +If we want a State for our BlogEntry, we have to define a relation +``in_state`` in the schema of BlogEntry. So we add the line ``in_state (...)``:: class BlogEntry(EntityType): @@ -86,59 +58,64 @@ entry_of = SubjectRelation('Blog', cardinality='?*') in_state = SubjectRelation('State', cardinality='1*') -As you updated the schema, you will have re-execute ``cubicweb-ctl db-init`` +As you updated the schema, you have to re-execute ``cubicweb-ctl db-init`` to initialize the database and migrate your existing entities. + [WRITE ABOUT MIGRATION] Create states, transitions and group permissions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -At the time the ``postcreate.py`` script is executed, several methods -can be used. They are all defined in the ``class ServerMigrationHelper``. -We will only discuss the method we use to create a wrokflow here. +The ``postcreate.py`` script is executed in a special environment, adding +several `CubicWeb` primitives that can be used. +They are all defined in the ``class ServerMigrationHelper``. +We will only discuss the methods we use to create a workflow in this example. To define our workflow for BlogDemo, please add the following lines to ``migration/postcreate.py``:: _ = unicode - moderators = add_entity('EGroup', name=u"moderators") + moderators = add_entity('EGroup', name=u"moderators") + +This adds the `moderators` user group. + +:: submitted = add_state(_('submitted'), 'BlogEntry', initial=True) published = add_state(_('published'), 'BlogEntry') +``add_state`` expects as first argument the name of the state you want +to create, then the entity type on which the state can be applied, +and an optional argument to say if it is supposed to be the initial state +of the entity type. + +:: + add_transition(_('approve_blogentry'), 'BlogEntry', (submitted,), published, ('moderators', 'managers'),) + +``add_transition`` expects + + * as the first argument the name of the + transition, then the entity type on which the transition can be applied, + * then the list of states on which the transition can be trigged, + * the target state of the transition, + * and the permissions + (e.g. a list of user groups who can apply the transition; the user + has to belong to at least one of the listed group to perform the action). + +:: + checkpoint() .. note:: Do not forget to add the `_()` in front of all states and transitions names while creating a workflow so that they will be identified by the i18n catalog scripts. -``add_entity`` is used here to define the new group of users that we -need to define the transitions, `moderators`. -If this group required by the transition is not defined before the -transition is created, it will not create the relation `transition -require the group moderator`. - -``add_state`` expects as the first argument the name of the state you are -willing to create, then the entity type on which the state can be applied, -and an optionnal argument to set if the state is the initial state -of the entity type or not. - -``add_transition`` expects as the first argument the name of the -transition, then the entity type on which we can apply the transition, -then the list of possible initial states from which the transition -can be applied, the target state of the transition, and the permissions -(e.g. list of the groups of users who can apply the transition, the user -needs to belong to at least one of the listed group). - - -We could have also added a RQL condition in addition to a group to -which the user should belong to. - -If we use both RQL condition and group, the two must be satisfied -for the user to be allowed to apply the transition. +In addition to the user group condition, we could have added a RQL condition. +In this case, the user can only perform the action if +the two conditions are satisfied. If we use a RQL condition on a transition, we can use the following variables: @@ -150,8 +127,40 @@ .. image:: images/lax-book.03-transitions-view.en.png -You can now notice that in the actions box of a BlogEntry, the state -is now listed as well as the possible transitions from this state -defined by the workflow. This transition, as defined in the workflow, -will only being displayed for the users belonging to the group -moderators of managers. +You can notice that in the action box of a BlogEntry, the state +is now listed as well as the possible transitions defined by the workflow. +The transitions will only be displayed for users having the right permissions. +In our example, the transition `approve_blogentry` will only be displayed +for the users belonging to the group `moderators` or `managers`. + + +Under the hood +~~~~~~~~~~~~~~ + +A workflow is a collection of entities of type ``State`` and of type ``Transition`` +which are standard `CubicWeb` entity types. +For instance, the following lines:: + + submitted = add_state(_('submitted'), 'BlogEntry', initial=True) + published = add_state(_('published'), 'BlogEntry') + +will create two entities of type ``State``, one with name 'submitted', and the other +with name 'published'. Whereas:: + + add_transition(_('approve_blogentry'), 'BlogEntry', (submitted,), published, ('moderators', 'managers'),) + +will create an entity of type ``Transition`` with name 'approve_blogentry' which will +be linked to the ``State`` entities created before. +As a consequence, we could use the administration interface to do these operations. +But it is not recommanded because it will be uselessly complicated +and will be only local to your instance. + + +Indeed, if you create the states and transitions through the user interface, +next time you initialize the database +you will have to re-create all the entities. +The user interface should only be a reference for you to view the states +and transitions, but is not the appropriate interface to define your +application workflow. + + diff -r 25480a710422 -r 9db3648c476d doc/book/en/B0030-data-as-objects.en.txt --- a/doc/book/en/B0030-data-as-objects.en.txt Thu Apr 02 15:21:00 2009 +0200 +++ b/doc/book/en/B0030-data-as-objects.en.txt Thu Apr 02 15:21:55 2009 +0200 @@ -4,15 +4,15 @@ Data as objects =============== -We will in this chapter introduce the objects that are used to handle +In this chapter, we will introduce the objects that are used to handle the data stored in the database. Classes `Entity` and `AnyEntity` -------------------------------- -To provide a specific behavior for each entity, we just need to define -a class inheriting from `cubicweb.entities.AnyEntity`. In general, we have -to defined those classes in a module of `entities` package of an application +To provide a specific behavior for each entity, we have to define +a class inheriting from `cubicweb.entities.AnyEntity`. In general, we +define this class in a module of `entities` package of an application so that it will be available on both server and client side. The class `AnyEntity` is loaded dynamically from the class `Entity` @@ -22,7 +22,7 @@ Descriptors are added when classes are registered in order to initialize the class according to its schema: -* we can access the defined attributes in the schema thanks the attributes of +* we can access the defined attributes in the schema thanks to the attributes of the same name on instances (typed value) * we can access the defined relations in the schema thanks to the relations of @@ -33,12 +33,12 @@ * `has_eid()`, returns true is the entity has an definitive eid (e.g. not in the creation process) -* `check_perm(action)`, checks if the user has the permission to execcute the +* `check_perm(action)`, checks if the user has the permission to execute the requested action on the entity :Formatting and output generation: - * `view(vid, **kwargs)`, apply the given view to the entity + * `view(vid, **kwargs)`, applies the given view to the entity * `absolute_url(**kwargs)`, returns an absolute URL to access the primary view of an entity @@ -118,30 +118,31 @@ *rtags* ------- -*rtags* allows to specify certain behaviors of relations relative to a given +*rtags* allow to specify certain behaviors of relations relative to a given entity type (see later). They are defined on the entity class by the attribute -`rtags` which is a dictionnary with as its keys the triplet :: +`rtags` which is a dictionnary with as keys the triplets :: , , -and as the values a `set` or a tuple of markers defining the properties that +and as values a `set` or a tuple of markers defining the properties that apply to this relation. It is possible to simplify this dictionnary: * if we want to specifiy a single marker, it is not necessary to - use a tuple as the value, the marker by itself (characters string) + use a tuple as value, the marker by itself (character string) is enough * if we only care about a single type of relation and not about the target and the context position (or when this one is not ambigous), we can simply - use the name of the relation type as the key + use the name of the relation type as key * if we want a marker to apply independently from the target entity type, - we have to use the string `*` as the target entity type + we have to use the string `*` as target entity type Please note that this dictionnary is *treated at the time the class is created*. It is automatically merged with the parent class(es) (no need to copy the -dictionnary from the parent class to modify it). Also, modify it after the +dictionnary from the parent class to modify it). Also, modifying it after the class is created will not have any effect... .. include:: B0031-define-entities.en.txt + diff -r 25480a710422 -r 9db3648c476d doc/book/en/B0031-define-entities.en.txt --- a/doc/book/en/B0031-define-entities.en.txt Thu Apr 02 15:21:00 2009 +0200 +++ b/doc/book/en/B0031-define-entities.en.txt Thu Apr 02 15:21:55 2009 +0200 @@ -5,8 +5,8 @@ Dynamic default values `````````````````````` -It is possible to define in the schema *static* default values. -It is also possible to define in the schema *dynamic* default values +It is possible to define *static* default values in the schema. +It is also possible to define *dynamic* default values by defining in the entity class a method `default_` for a given attribute. @@ -118,20 +118,22 @@ 1. we consider that the first column contains the entities to constraint 2. we collect the first entity of the table (row 0) to represent all the others -3. for all the others variables defined in the original request: +3. for all the other variables defined in the original request: - 1. if the varaible is related to the main variable by at least one relation + 1. if the variable is related to the main variable by at least one relation 2. we call the method ``filterform_vocabulary(rtype, x)`` on the entity, if nothing is returned (meaning a tuple `Non`, see below), we go to the next variable, otherwise a form filtering element is created based on the vocabulary values returned -4. there is no others limitations to the `RQL`, it can include sorting, grouping - conditions... Javascripts functions are used to regenerate a request based on the +4. there are no other limitations to the `RQL`, it can include sorting, grouping + conditions... JavaScript functions are used to regenerate a request based on the initial request and on the selected values from the filtering form. The method ``filterform_vocabulary(rtype, x, var, rqlst, args, cachekey)`` takes -the name of a relation and the target as parameters, which indicates of the +the name of a relation and the target as parameters, +[XXX what does it mean ?] + which indicates of the entity on which we apply the method is subject or object of the relation. It has to return: @@ -157,18 +159,18 @@ class Ticket(AnyEntity): - ... + ... - def filterform_vocabulary(self, rtype, x, var, rqlst, args, cachekey): - _ = self.req._ - if rtype == 'type': - return 'string', [(x, _(x)) for x in ('bug', 'story')] - if rtype == 'priority': - return 'string', [(x, _(x)) for x in ('minor', 'normal', 'important')] - if rtype == 'done_in': - rql = insert_attr_select_relation(rqlst, var, rtype, 'num') - return 'eid', self.req.execute(rql, args, cachekey) - return super(Ticket, self).filterform_vocabulary(rtype, x, var, rqlst, + def filterform_vocabulary(self, rtype, x, var, rqlst, args, cachekey): + _ = self.req._ + if rtype == 'type': + return 'string', [(x, _(x)) for x in ('bug', 'story')] + if rtype == 'priority': + return 'string', [(x, _(x)) for x in ('minor', 'normal', 'important')] + if rtype == 'done_in': + rql = insert_attr_select_relation(rqlst, var, rtype, 'num') + return 'eid', self.req.execute(rql, args, cachekey) + return super(Ticket, self).filterform_vocabulary(rtype, x, var, rqlst, args, cachekey) .. note:: diff -r 25480a710422 -r 9db3648c476d doc/book/en/C011-installation.en.txt --- a/doc/book/en/C011-installation.en.txt Thu Apr 02 15:21:00 2009 +0200 +++ b/doc/book/en/C011-installation.en.txt Thu Apr 02 15:21:55 2009 +0200 @@ -35,8 +35,14 @@ apt-get install cubicweb apt-get install cubicweb-dev +`cubicweb` installs the framework itself, allowing you to create +new applications. -This is it! +`cubicweb-dev` installs the development environment allowing you to +develop new cubes. + +There is also a wide variety of cubes listed on http://www.cubicweb.org/Project available as debian packages and tarball. + Install from source ``````````````````` @@ -92,7 +98,7 @@ Your new cubes will be placed in `/usr/share/cubicweb/cubes` and your applications will be placed in `/etc/cubicweb.d`. -To use other directories you will have to configure the +To use others directories then you will have to configure the following environment variables as follows:: export CW_CUBES_PATH=~/lib/cubes @@ -111,7 +117,7 @@ .. note:: If you already have an existing cluster and postgres server - running you do not require to execute the initilization step + running, you do not require to execute the initilization step of your Postgres database. * First you have to initialize the database Postgres with the command ``initdb``. @@ -130,14 +136,24 @@ $ chown username /path/to/pgsql -* Create a superuser for `CubicWeb` instance:: +* The database authentication can be either set to `ident sameuser` + or `md5`. + If set to `md5`, make sure to use an existing user + of your database. + If set to `ident sameuser`, make sure that your + client's operating system user name has a matching user in + the database. If not, please do as follow to create a user:: $ su $ su - postgres $ createuser -s username - Initialize the password of the superuser you just created for your - database:: + If created with the options -P (for password prompt, + ``createuser -s -P username``), the password will be encrypted with + the method set in the configuration file ``pg_hba.conf``. + If you do not use this option, then the default value will be null + and this require to set the password in the database itself. + To do so: :: $ su $ su - postgres @@ -151,13 +167,17 @@ instance with `cubicweb-ctl create` to initialize the database of your application. +.. note:: + The authentication method can be configured in ``pg_hba.conf``. + + .. FIXME Are these steps really necessary? It seemed to work without. -* installation of plain-text index extension :: +* Installation of plain-text index extension :: cat /usr/share/postgresql/8.3/contrib/tsearch2.sql | psql -U username template1 -* installation of plpythonu language by default :: +* Installation of plpythonu language by default :: createlang -U pgadmin plpythonu template1 diff -r 25480a710422 -r 9db3648c476d doc/book/en/C040-rql.en.txt --- a/doc/book/en/C040-rql.en.txt Thu Apr 02 15:21:00 2009 +0200 +++ b/doc/book/en/C040-rql.en.txt Thu Apr 02 15:21:55 2009 +0200 @@ -140,6 +140,14 @@ X is Person, X name N, X first_name P + Note: You can not specify several types with * ... where X is FirstType or X is SecondType*. + To specify several types explicitely, you have to do + + :: + + Any X where X is in (FirstType, SecondType) + + Insertion query --------------- diff -r 25480a710422 -r 9db3648c476d doc/book/en/Z013-blog-less-ten-minutes.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/Z013-blog-less-ten-minutes.en.txt Thu Apr 02 15:21:55 2009 +0200 @@ -0,0 +1,84 @@ +.. -*- coding: utf-8 -*- + +Have a blog ready in less than ten minutes! +------------------------------------------- + +Installation +~~~~~~~~~~~~ + +You need to install the following packages:: + + cubicweb, cubicweb-blog + +The package `cubicweb` is installing the command `cubicweb-ctl` that +will allow you to create new application. + +The package `cubicweb-blog` is installing the blogging support for the +`CubicWeb` framework. + +Application creation +~~~~~~~~~~~~~~~~~~~~ + +Creation and initialization of your application by running:: + + cubicweb-ctl create blog myblog + +*myblog* is the name of the application you are creating. + +*blog* is the name of the component on which your application +is based. + +Application launch +~~~~~~~~~~~~~~~~~~ + +Your application is now ready to go:: + + cubicweb-ctl start -D myblog + +This is it. Your blog is ready to you. Go to http://localhost:8080 and enjoy!! + + +A little code snapshot from behind the scene +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The component `blog`, referred as a `cube` in the book +(see :ref:`TermsVocabulary` for a complete definition), defines +a data model in ``/usr/share/cubicweb/cubes/blog/schema.py``. +Here is the corresponding Python code:: + + from cubicweb.schema import format_constraint + + class Blog(EntityType): + title = String(maxsize=50, required=True) + description_format = String(meta=True, internationalizable=True, maxsize=50, + default='text/rest', constraints=[format_constraint]) + description = String() + rss_url = String(maxsize=128, description=_('blog\'s rss url (useful for when using external site such as feedburner)')) + + + class BlogEntry(EntityType): + title = String(required=True, fulltextindexed=True, maxsize=256) + content_format = String(meta=True, internationalizable=True, maxsize=50, + default='text/rest', constraints=[format_constraint]) + content = String(required=True, fulltextindexed=True) + entry_of = SubjectRelation('Blog', cardinality='?*') + +Two types of entities are defined here: Blog and BlogEntry. + +A Blog is defined by a title, a description and its format and a +RSS URL to provide RSS feed. + +A BlogEntry is defined by a title, a content and its format and +a relation to a Blog, meaning a BlogEntry belongs to a Blog. + + +Next step +~~~~~~~~~ + +This was a brief demonstration of the re-usability of cubes and a way +to show how you can use `CubicWeb` straigth out of the box. + +As a developper, you'll want to know more about how to develop new +cubes and cutomize the views and this is what we talk about now. + + diff -r 25480a710422 -r 9db3648c476d doc/book/en/index.txt --- a/doc/book/en/index.txt Thu Apr 02 15:21:00 2009 +0200 +++ b/doc/book/en/index.txt Thu Apr 02 15:21:55 2009 +0200 @@ -42,7 +42,6 @@ .. toctree:: - :maxdepth: 2 A000-introduction.en.txt B000-development.en.txt diff -r 25480a710422 -r 9db3648c476d i18n/en.po --- a/i18n/en.po Thu Apr 02 15:21:00 2009 +0200 +++ b/i18n/en.po Thu Apr 02 15:21:55 2009 +0200 @@ -1434,6 +1434,10 @@ msgid "csv export" msgstr "" +#, python-format +msgid "currently attached file: %s" +msgstr "" + msgid "data directory url" msgstr "" @@ -1546,7 +1550,8 @@ msgid "destination_state_object" msgstr "destination of" -msgid "detach attached file" +#, python-format +msgid "detach attached file %s" msgstr "" msgid "detailed schema view" diff -r 25480a710422 -r 9db3648c476d i18n/es.po --- a/i18n/es.po Thu Apr 02 15:21:00 2009 +0200 +++ b/i18n/es.po Thu Apr 02 15:21:55 2009 +0200 @@ -104,6 +104,10 @@ msgstr "%d semanas" #, python-format +msgid "%d years" +msgstr "" + +#, python-format msgid "%s error report" msgstr "%s reporte de errores" @@ -1487,6 +1491,10 @@ msgid "csv export" msgstr "exportar CSV" +#, python-format +msgid "currently attached file: %s" +msgstr "" + msgid "data directory url" msgstr "url del repertorio de datos" @@ -1612,8 +1620,9 @@ msgid "destination_state_object" msgstr "destino de" -msgid "detach attached file" -msgstr "soltar el archivo existente" +#, python-format +msgid "detach attached file %s" +msgstr "" msgid "detailed schema view" msgstr "vista detallada del esquema" @@ -2997,6 +3006,9 @@ #~ "langue par dÈfaut (regarder le rÈpertoire i18n de l'application pour voir " #~ "les langues disponibles)" +#~ msgid "detach attached file" +#~ msgstr "soltar el archivo existente" + #~ msgid "filter" #~ msgstr "filtrer" diff -r 25480a710422 -r 9db3648c476d i18n/fr.po --- a/i18n/fr.po Thu Apr 02 15:21:00 2009 +0200 +++ b/i18n/fr.po Thu Apr 02 15:21:55 2009 +0200 @@ -1492,6 +1492,10 @@ msgid "csv export" msgstr "export CSV" +#, python-format +msgid "currently attached file: %s" +msgstr "fichie actuellement attaché %s" + msgid "data directory url" msgstr "url du répertoire de données" @@ -1616,8 +1620,9 @@ msgid "destination_state_object" msgstr "destination de" -msgid "detach attached file" -msgstr "détacher le fichier existant" +#, python-format +msgid "detach attached file %s" +msgstr "détacher le fichier existant %s" msgid "detailed schema view" msgstr "vue détaillée du schéma" @@ -3002,6 +3007,9 @@ #~ "langue par défaut (regarder le répertoire i18n de l'application pour voir " #~ "les langues disponibles)" +#~ msgid "detach attached file" +#~ msgstr "détacher le fichier existant" + #~ msgid "filter" #~ msgstr "filtrer" diff -r 25480a710422 -r 9db3648c476d web/widgets.py --- a/web/widgets.py Thu Apr 02 15:21:00 2009 +0200 +++ b/web/widgets.py Thu Apr 02 15:21:55 2009 +0200 @@ -486,11 +486,15 @@ wdgs.append(ewdg.edit_render(entity, includehelp=True)) wdgs.append(u'
') wdgs.append(u'') - if entity.has_eid() and not self.required(entity): - # trick to be able to delete an uploaded file - wdgs.append(u'
') - wdgs.append(checkbox(eid_param('__%s_detach' % self.rname, entity.eid), False)) - wdgs.append(req._('detach attached file')) + if entity.has_eid(): + if not self.required(entity): + # trick to be able to delete an uploaded file + wdgs.append(u'
') + wdgs.append(checkbox(eid_param('__%s_detach' % self.rname, entity.eid), False)) + wdgs.append(req._('detach attached file %s' % entity.dc_title())) + else: + wdgs.append(u'
') + wdgs.append(req._('currently attached file: %s' % entity.dc_title())) return '\n'.join(wdgs) def _edit_render(self, entity):