/trunk/Coel.launch |
---|
9,9 → 9,9 |
<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/> |
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH"> |
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER" javaProject="coel" path="1" type="4"/> "/> |
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.USER_LIBRARY/GWT_1_5_3" path="3" type="4"/> "/> |
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.USER_LIBRARY/GXT_1_2_1" path="3" type="4"/> "/> |
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/coel/src" path="3" type="2"/> "/> |
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.USER_LIBRARY/GWT_1.5.3" path="3" type="4"/> "/> |
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.USER_LIBRARY/GXT_1.2.1" path="3" type="4"/> "/> |
</listAttribute> |
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/> |
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.GWTShell"/> |
/trunk/src/org/tela_botanica/client/Mediateur.java |
---|
New file |
0,0 → 1,119 |
package org.tela_botanica.client; |
import org.tela_botanica.client.composants.IdentificationFenetre; |
import org.tela_botanica.client.modeles.Menu; |
import org.tela_botanica.client.modeles.Structure; |
import org.tela_botanica.client.modeles.ListeStructure; |
import org.tela_botanica.client.vues.ContenuPanneauVue; |
import org.tela_botanica.client.vues.EntetePanneauVue; |
import org.tela_botanica.client.vues.StructureDetailPanneauVue; |
import org.tela_botanica.client.vues.StructureVue; |
import org.tela_botanica.client.vues.MenuPanneauVue; |
import com.extjs.gxt.ui.client.Registry; |
import com.extjs.gxt.ui.client.Style.LayoutRegion; |
import com.extjs.gxt.ui.client.util.Margins; |
import com.extjs.gxt.ui.client.widget.Viewport; |
import com.extjs.gxt.ui.client.widget.layout.BorderLayout; |
import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData; |
import com.google.gwt.user.client.Window; |
import com.google.gwt.user.client.ui.RootPanel; |
public class Mediateur { |
private Viewport viewport; |
private EntetePanneauVue panneauNord = null; |
private MenuPanneauVue panneauOuest = null; |
private ContenuPanneauVue panneauCentre = null; |
public Mediateur() { |
// Enregistrement du Médiateur dans le Registre |
Registry.register(RegistreId.MEDIATEUR, this); |
// Création du Modèle qui s'enregistre lui même dans le Registre |
new Modele(); |
// Création du Viewport qui contient la disposition globale de l'application |
viewport = new Viewport(); |
viewport.setLayout(new BorderLayout()); |
// Création des différents panneaux |
creerPanneauNord(); |
creerPanneauOuest(); |
creerPanneauCentral(); |
// Registry utile car présent partout! |
Registry.register(RegistreId.VIEWPORT, viewport); |
Registry.register(RegistreId.PANNEAU_OUEST, panneauOuest); |
Registry.register(RegistreId.PANNEAU_CENTRE, panneauCentre); |
// Chargement du menu |
chargeMenu(panneauOuest.listerMenu()); |
// Retour à GWT du Viewport une fois constuit |
RootPanel.get().add(viewport); |
} |
private void creerPanneauNord() { |
panneauNord = new EntetePanneauVue(); |
BorderLayoutData regionNord = new BorderLayoutData(LayoutRegion.NORTH, 100); |
regionNord.setCollapsible(true); |
regionNord.setFloatable(true); |
regionNord.setSplit(false); |
regionNord.setMargins(new Margins(5, 5, 0, 5)); |
viewport.add(panneauNord, regionNord); |
} |
private void creerPanneauOuest() { |
panneauOuest = new MenuPanneauVue(); |
BorderLayoutData regionOuest = new BorderLayoutData(LayoutRegion.WEST, 200); |
regionOuest.setSplit(true); |
regionOuest.setCollapsible(true); |
regionOuest.setMargins(new Margins(5)); |
viewport.add(panneauOuest, regionOuest); |
} |
private void creerPanneauCentral() { |
panneauCentre = new ContenuPanneauVue(); |
BorderLayoutData regionCentre = new BorderLayoutData(LayoutRegion.CENTER); |
regionCentre.setMargins(new Margins(5, 5, 5, 0)); |
viewport.add(panneauCentre, regionCentre); |
} |
public void chargeMenu(Menu menus) { |
((MenuPanneauVue) Registry.get(RegistreId.PANNEAU_OUEST)).rafraichir(menus); |
} |
public void clicMenu(String s) { |
panneauCentre.removeAll(); |
if (s.equals("Institutions")) { |
((Modele) Registry.get(RegistreId.MODELE)).obtenirListeInstitutions(); |
} else { |
Window.alert("Non implémenté!"); |
} |
panneauCentre.layout(); |
} |
public void clicIdentification() { |
// Gestion du login |
IdentificationFenetre dialog = new IdentificationFenetre(); |
dialog.setClosable(false); |
dialog.show(); |
} |
public void clicListeInstitution(Structure institution) { |
((StructureDetailPanneauVue) Registry.get(RegistreId.PANNEAU_INSTITUTION_DETAIL)).rafraichir(institution); |
} |
public void afficherListeInstitutions(ListeStructure nouvelleDonnees) { |
// TODO : créer dès l'initialisation de l'application InsitutionVue et la cacher |
StructureVue institutionVue = new StructureVue(); |
panneauCentre.add(institutionVue); |
institutionVue.rafraichir(nouvelleDonnees); |
} |
} |
/trunk/src/org/tela_botanica/client/RegistreId.java |
---|
New file |
0,0 → 1,12 |
package org.tela_botanica.client; |
public final class RegistreId { |
public static final String APPLI_NOM = "Application Nom"; |
public static final String CONFIG = "Configuration"; |
public static final String MEDIATEUR = "Médiateur"; |
public static final String MODELE = "Modèle"; |
public static final String VIEWPORT = "Viewport"; |
public static final String PANNEAU_OUEST = "Panneau ouest"; |
public static final String PANNEAU_CENTRE = "Panneau central"; |
public static final String PANNEAU_INSTITUTION_DETAIL = "Panneau Institution détail"; |
} |
/trunk/src/org/tela_botanica/client/Coel.java |
---|
1,37 → 1,26 |
package org.tela_botanica.client; |
import org.tela_botanica.client.controleurs.AppControleur; |
import org.tela_botanica.client.controleurs.InstitutionControleur; |
import org.tela_botanica.client.modeles.Configuration; |
import com.extjs.gxt.ui.client.GXT; |
import com.extjs.gxt.ui.client.Registry; |
import com.extjs.gxt.ui.client.mvc.Dispatcher; |
import com.extjs.gxt.ui.client.util.Theme; |
import com.google.gwt.core.client.EntryPoint; |
/** |
/** |
* Entry point classes define <code>onModuleLoad()</code>. |
*/ |
public class Coel implements EntryPoint { |
public static final String APPLI_NOM = "Application Nom"; |
public void onModuleLoad() { |
/** |
* This is the entry point method. |
*/ |
public void onModuleLoad() { |
GXT.setDefaultTheme(Theme.GRAY, true); |
GXT.hideLoadingPanel("loading"); |
Registry.register(APPLI_NOM, "Coel"); |
Dispatcher dispatcher = Dispatcher.get(); |
dispatcher.addController(new AppControleur()); |
//dispatcher.addController(new RechercheControleur()); |
dispatcher.addController(new InstitutionControleur()); |
//dispatcher.addController(new CollectionControleur()); |
//dispatcher.addController(new PersonneControleur()); |
//dispatcher.addController(new PublicationControleur()); |
dispatcher.dispatch(AppEvenements.Login); |
} |
Registry.register(RegistreId.APPLI_NOM, "Coel"); |
Registry.register(RegistreId.CONFIG, new Configuration()); |
new Mediateur(); |
} |
} |
/trunk/src/org/tela_botanica/client/vues/InstitutionVue.java |
---|
File deleted |
/trunk/src/org/tela_botanica/client/vues/StructureListePanneauVue.java |
---|
New file |
0,0 → 1,112 |
package org.tela_botanica.client.vues; |
import java.util.ArrayList; |
import java.util.Iterator; |
import java.util.List; |
import org.tela_botanica.client.Mediateur; |
import org.tela_botanica.client.RegistreId; |
import org.tela_botanica.client.interfaces.Rafraichissable; |
import org.tela_botanica.client.modeles.Structure; |
import org.tela_botanica.client.modeles.ListeStructure; |
import com.extjs.gxt.ui.client.Registry; |
import com.extjs.gxt.ui.client.Style.SelectionMode; |
import com.extjs.gxt.ui.client.binder.TableBinder; |
import com.extjs.gxt.ui.client.event.SelectionChangedEvent; |
import com.extjs.gxt.ui.client.event.SelectionChangedListener; |
import com.extjs.gxt.ui.client.store.ListStore; |
import com.extjs.gxt.ui.client.widget.ContentPanel; |
import com.extjs.gxt.ui.client.widget.layout.FitLayout; |
import com.extjs.gxt.ui.client.widget.table.Table; |
import com.extjs.gxt.ui.client.widget.table.TableColumn; |
import com.extjs.gxt.ui.client.widget.table.TableColumnModel; |
import com.extjs.gxt.ui.client.widget.toolbar.TextToolItem; |
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar; |
import com.google.gwt.user.client.Window; |
public class StructureListePanneauVue extends ContentPanel implements Rafraichissable { |
private Mediateur coelMediateur = null ; |
private Table table = null; |
private ListStore<Structure> store = null; |
private TableBinder<Structure> binder = null; |
public StructureListePanneauVue() { |
coelMediateur = Registry.get(RegistreId.MEDIATEUR); |
ToolBar toolBar = new ToolBar(); |
TextToolItem ajouter = new TextToolItem("Ajouter"); |
ajouter.setIconStyle("icone-ajouter"); |
toolBar.add(ajouter); |
TextToolItem modifier = new TextToolItem("Modifier"); |
modifier.setIconStyle("icone-modifier"); |
toolBar.add(modifier); |
TextToolItem supprimer = new TextToolItem("Supprimer"); |
supprimer.setIconStyle("icone-supprimer"); |
toolBar.add(supprimer); |
setTopComponent(toolBar); |
List<TableColumn> columns = new ArrayList<TableColumn>(); |
// ATTENTION : les noms des colonnes doivent correspondrent aux noms variables de la classe utilisée dans la liste |
columns.add(new TableColumn("ville", "Ville", .3f)); |
columns.add(new TableColumn("nom", "Nom", .7f)); |
TableColumnModel cm = new TableColumnModel(columns); |
table = new Table(cm); |
table.setSelectionMode(SelectionMode.MULTI); |
table.setBorders(false); |
add(table); |
store = new ListStore<Structure>(); |
binder = new TableBinder<Structure>(table, store); |
binder.setAutoSelect(true); |
binder.addSelectionChangedListener(new SelectionChangedListener<Structure>() { |
public void selectionChanged(SelectionChangedEvent<Structure> event) { |
Structure m = (Structure) event.getSelectedItem(); |
clicListe(m); |
} |
}); |
setLayout(new FitLayout()); |
} |
public ListStore<Structure> getStore() { |
return store; |
} |
public TableBinder<Structure> getBinder() { |
return binder; |
} |
private void clicListe(Structure institution) { |
coelMediateur.clicListeInstitution(institution); |
} |
public void rafraichir(Object nouvelleDonnees) { |
if (nouvelleDonnees instanceof ListeStructure) { |
ListeStructure listeInstitutions = (ListeStructure) nouvelleDonnees; |
setHeading("Institutions"); |
List<Structure> liste = new ArrayList<Structure>(); |
for (Iterator<String> it = listeInstitutions.keySet().iterator(); it.hasNext();) { |
liste.add(listeInstitutions.get(it.next())); |
} |
store.removeAll(); |
store.add((List<Structure>) liste); |
// Test pour savoir si la liste contient des éléments |
if (listeInstitutions.size() > 0) { |
binder.setSelection((Structure) listeInstitutions.get(0)); |
} |
} |
} |
} |
/trunk/src/org/tela_botanica/client/vues/StructureDetailPanneauVue.java |
---|
New file |
0,0 → 1,93 |
package org.tela_botanica.client.vues; |
import org.tela_botanica.client.RegistreId; |
import org.tela_botanica.client.interfaces.Rafraichissable; |
import org.tela_botanica.client.modeles.Structure; |
import org.tela_botanica.client.modeles.ListeStructure; |
import com.extjs.gxt.ui.client.Registry; |
import com.extjs.gxt.ui.client.Style.Scroll; |
import com.extjs.gxt.ui.client.util.Format; |
import com.extjs.gxt.ui.client.util.Params; |
import com.extjs.gxt.ui.client.widget.ContentPanel; |
import com.extjs.gxt.ui.client.widget.Html; |
import com.extjs.gxt.ui.client.widget.layout.FitLayout; |
public class StructureDetailPanneauVue extends ContentPanel implements Rafraichissable { |
private ContentPanel content; |
private Html header; |
private String enteteHTML = "<div class='coel-detail'><h1>{0}</h1><h2>{1}</h2></div>"; |
private String contenuHTML = "<div style='padding: 12px;'><h2>Renseignements administratifs</h2><span style='font-weight:bold;'>Condition d'accès :</span> {9}<br /><span style='font-weight:bold;'>Adresse :</span> {1}, {2} {3}, {4}, {5}<br /><span style='font-weight:bold;'>Téléphone :</span> {6}<br /><span style='font-weight:bold;'>Fax :</span> {7}<br /><span style='font-weight:bold;'>Courriel :</span> {8}<br />{0}</div>"; |
private String structureNom = null; |
private String structureVille = null; |
private String structureDescription = null; |
public StructureDetailPanneauVue() { |
Registry.register(RegistreId.PANNEAU_INSTITUTION_DETAIL, this); |
setHeaderVisible(false); |
setLayout(new FitLayout()); |
content = new ContentPanel(); |
content.setBodyBorder(false); |
content.setHeaderVisible(false); |
content.setScrollMode(Scroll.AUTO); |
header = new Html(); |
header.setStyleName("coel-detail"); |
content.setTopComponent(header); |
add(content); |
} |
public void afficherDetailInstitution(Structure structure) { |
if (structure != null) { |
content.removeAll(); |
structureNom = structure.getNom(); |
structureVille = structure.getVille(); |
structureDescription = structure.getDescription(); |
Params enteteParams = new Params(); |
enteteParams.add(structureNom); |
enteteParams.add(structureVille); |
String eHtml = Format.substitute(enteteHTML, enteteParams); |
header.getElement().setInnerHTML(eHtml); |
Params contenuParams = new Params(); |
contenuParams.add(structureDescription); |
contenuParams.add(structure.getAdresse01()); |
contenuParams.add(structure.getCodePostal()); |
contenuParams.add(structure.getVille()); |
contenuParams.add(structure.getRegion()); |
contenuParams.add(structure.getPays()); |
contenuParams.add(structure.getTelephone()); |
contenuParams.add(structure.getFax()); |
contenuParams.add(structure.getCourriel()); |
contenuParams.add(structure.getConditionAcces()); |
String cHtml = Format.substitute(contenuHTML, contenuParams); |
content.addText(cHtml); |
layout(); |
} else { |
header.setHtml(""); |
content.removeAll(); |
} |
} |
public void rafraichir(Object nouvelleDonnees) { |
if (nouvelleDonnees instanceof Structure) { |
afficherDetailInstitution((Structure) nouvelleDonnees); |
} else if (nouvelleDonnees instanceof ListeStructure) { |
ListeStructure listeInstitutions = (ListeStructure) nouvelleDonnees; |
// Test pour savoir si la liste contient des éléments |
if (listeInstitutions.size() == 0) { |
afficherDetailInstitution(null); |
} |
} |
} |
} |
/trunk/src/org/tela_botanica/client/vues/EntetePanneauVue.java |
---|
New file |
0,0 → 1,61 |
package org.tela_botanica.client.vues; |
import org.tela_botanica.client.RegistreId; |
import org.tela_botanica.client.modeles.Configuration; |
import com.extjs.gxt.ui.client.Registry; |
import com.extjs.gxt.ui.client.Style; |
import com.extjs.gxt.ui.client.Style.Orientation; |
import com.extjs.gxt.ui.client.event.ComponentEvent; |
import com.extjs.gxt.ui.client.event.SelectionListener; |
import com.extjs.gxt.ui.client.widget.HtmlContainer; |
import com.extjs.gxt.ui.client.widget.Info; |
import com.extjs.gxt.ui.client.widget.LayoutContainer; |
import com.extjs.gxt.ui.client.widget.button.Button; |
import com.extjs.gxt.ui.client.widget.button.ButtonBar; |
import com.extjs.gxt.ui.client.widget.button.SplitButton; |
import com.extjs.gxt.ui.client.widget.layout.RowData; |
import com.extjs.gxt.ui.client.widget.layout.RowLayout; |
import com.extjs.gxt.ui.client.widget.menu.Menu; |
import com.extjs.gxt.ui.client.widget.menu.MenuItem; |
public class EntetePanneauVue extends LayoutContainer { |
public EntetePanneauVue() { |
setLayout(new RowLayout(Orientation.HORIZONTAL)); |
setId("coel-entete"); |
// TODO : ajouter la gestion de l'identification |
HtmlContainer html = new HtmlContainer(); |
StringBuffer sb = new StringBuffer(); |
sb.append(" <div id='coel-titre'>Collections en Ligne Demo</div>"); |
html.setHtml(sb.toString()); |
html.setEnableState(false); |
// Création de l'écouteur |
SelectionListener<ComponentEvent> ecouteur = new SelectionListener<ComponentEvent>() { |
public void componentSelected(ComponentEvent ce) { |
Button btn = (Button) ce.component; |
Info.display(btn.getText(), "Chargement de la fenêtre '{0}' en cours...", btn.getText()); |
} |
}; |
ButtonBar buttonBar = new ButtonBar(); |
buttonBar.setButtonAlign(Style.HorizontalAlignment.RIGHT); |
buttonBar.add(new Button("Paramêtres", ecouteur)); |
buttonBar.add(new Button("Aide", ecouteur)); |
buttonBar.add(new Button("Identifiez vous...", ecouteur)); |
SplitButton button = new SplitButton(); |
button.setText("Changez d'application..."); |
button.addSelectionListener(ecouteur); |
Menu menu = new Menu(); |
String urlCel = ((Configuration) Registry.get(RegistreId.CONFIG)).getCelUrl(); |
menu.add(new MenuItem("<a href='"+urlCel+"'>Carnet en ligne</a>")); |
button.setMenu(menu); |
buttonBar.add(button); |
add(html, new RowData(.3, 1)); |
add(buttonBar, new RowData(.7, 50)); |
} |
} |
/trunk/src/org/tela_botanica/client/vues/MenuPanneauVue.java |
---|
New file |
0,0 → 1,69 |
package org.tela_botanica.client.vues; |
import org.tela_botanica.client.Mediateur; |
import org.tela_botanica.client.RegistreId; |
import org.tela_botanica.client.modeles.Menu; |
import com.extjs.gxt.ui.client.Events; |
import com.extjs.gxt.ui.client.Registry; |
import com.extjs.gxt.ui.client.event.Listener; |
import com.extjs.gxt.ui.client.event.TreeEvent; |
import com.extjs.gxt.ui.client.util.TreeBuilder; |
import com.extjs.gxt.ui.client.widget.ContentPanel; |
import com.extjs.gxt.ui.client.widget.layout.FitLayout; |
import com.extjs.gxt.ui.client.widget.tree.Tree; |
import com.extjs.gxt.ui.client.widget.tree.TreeItem; |
public class MenuPanneauVue extends ContentPanel { |
private Tree tree; |
public MenuPanneauVue() { |
setBodyBorder(false); |
setLayoutOnChange(true); |
setHeading("Menu"); |
setLayout(new FitLayout()); |
} |
public void rafraichir(Object nouvelleDonnees) { |
if (nouvelleDonnees instanceof Menu) { |
afficherMenu((Menu) nouvelleDonnees); |
} |
} |
private void afficherMenu(Menu menu) { |
tree = new Tree(); |
tree.getStyle().setLeafIconStyle("tree-folder"); |
tree.addListener(Events.OnClick, new Listener<TreeEvent>(){ |
public void handleEvent(TreeEvent be) { |
TreeItem f = tree.getSelectedItem(); |
selectionMenu(f.getText()); |
} |
}); |
TreeBuilder.buildTree(tree, menu); |
add(tree); |
} |
private void selectionMenu(String s) { |
((Mediateur) Registry.get(RegistreId.MEDIATEUR)).clicMenu(s); |
} |
public Menu listerMenu() { |
Menu menus = new Menu(); |
Menu menuInstitution = new Menu("Institutions"); |
Menu menuCollections = new Menu("Collections"); |
Menu menuPersonnes = new Menu("Personnes"); |
Menu menuPublications = new Menu("Publications"); |
menus.add(menuInstitution); |
menus.add(menuCollections); |
menus.add(menuPersonnes); |
menus.add(menuPublications); |
return menus; |
} |
} |
/trunk/src/org/tela_botanica/client/vues/StructureVue.java |
---|
New file |
0,0 → 1,50 |
package org.tela_botanica.client.vues; |
import org.tela_botanica.client.RegistreId; |
import org.tela_botanica.client.interfaces.Rafraichissable; |
import org.tela_botanica.client.modeles.ListeStructure; |
import com.extjs.gxt.ui.client.Registry; |
import com.extjs.gxt.ui.client.Style.LayoutRegion; |
import com.extjs.gxt.ui.client.util.Margins; |
import com.extjs.gxt.ui.client.widget.LayoutContainer; |
import com.extjs.gxt.ui.client.widget.layout.BorderLayout; |
import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData; |
import com.google.gwt.user.client.Window; |
public class StructureVue extends LayoutContainer implements Rafraichissable { |
private StructureListePanneauVue panneauInstitutionListe; |
private StructureDetailPanneauVue panneauInstitutionDetail; |
public StructureVue() { |
BorderLayout layout = new BorderLayout(); |
layout.setEnableState(false); |
setLayout(layout); |
panneauInstitutionListe = new StructureListePanneauVue(); |
this.add(panneauInstitutionListe, new BorderLayoutData(LayoutRegion.CENTER)); |
panneauInstitutionDetail = new StructureDetailPanneauVue(); |
BorderLayoutData southData = new BorderLayoutData(LayoutRegion.SOUTH, .5f, 200, 1000); |
southData.setSplit(true); |
southData.setMargins(new Margins(5, 0, 0, 0)); |
this.add(panneauInstitutionDetail, southData); |
} |
public void rafraichir(Object nouvelleDonnees) { |
if (nouvelleDonnees instanceof ListeStructure) { |
remplirListe((ListeStructure) nouvelleDonnees); |
} else { |
Window.alert("Problème!"); |
} |
} |
private void remplirListe(ListeStructure listeInstitutions) { |
LayoutContainer panneauCentre = (LayoutContainer) Registry.get(RegistreId.PANNEAU_CENTRE); |
panneauInstitutionListe.rafraichir(listeInstitutions); |
panneauInstitutionDetail.rafraichir(listeInstitutions); |
panneauCentre.layout(); |
} |
} |
/trunk/src/org/tela_botanica/client/vues/ContenuPanneauVue.java |
---|
New file |
0,0 → 1,11 |
package org.tela_botanica.client.vues; |
import com.extjs.gxt.ui.client.widget.LayoutContainer; |
import com.extjs.gxt.ui.client.widget.layout.FitLayout; |
public class ContenuPanneauVue extends LayoutContainer { |
public ContenuPanneauVue() { |
setLayout(new FitLayout()); |
} |
} |
/trunk/src/org/tela_botanica/client/interfaces/Rafraichissable.java |
---|
New file |
0,0 → 1,25 |
package org.tela_botanica.client.interfaces; |
/** |
* Toutes les classes qui recoivent des données de manières asynchrones ou |
* imprévisible implémentent cette interface. Elle permet de faire transiter le |
* rafraichissable jusqu'au DAO et d'appeler sa méthode rafraichir un fois les |
* données reçues, tout celà en préservant bien la séparation des rôles car les |
* classes qui font transiter le rafraichissable ne connaissent que cette |
* interface et pas le reste de l'objet |
* |
* @author aurelien |
* |
*/ |
public interface Rafraichissable { |
/** |
* Méthode de mise à jour d'un objet |
* |
* @param nouvelleDonnees |
* Un objet de n'importe quel type (programmation générique) qui |
* contient les données de mise à jour |
*/ |
public void rafraichir(Object nouvelleDonnees); |
} |
/trunk/src/org/tela_botanica/client/Modele.java |
---|
New file |
0,0 → 1,26 |
package org.tela_botanica.client; |
import org.tela_botanica.client.interfaces.Rafraichissable; |
import org.tela_botanica.client.modeles.ListeStructure; |
import org.tela_botanica.client.modeles.ListeStructureAsyncDao; |
import com.extjs.gxt.ui.client.Registry; |
// TODO : le transformer en SINGLETON |
public class Modele implements Rafraichissable { |
public Modele() { |
Registry.register(RegistreId.MODELE, this); |
} |
public void rafraichir(Object nouvelleDonnees) { |
if (nouvelleDonnees instanceof ListeStructure) { |
((Mediateur) Registry.get(RegistreId.MEDIATEUR)).afficherListeInstitutions((ListeStructure) nouvelleDonnees); |
} |
} |
public void obtenirListeInstitutions() { |
ListeStructureAsyncDao liDao = new ListeStructureAsyncDao(this); |
liDao.obtenirListeInstitution(); |
} |
} |
/trunk/src/org/tela_botanica/client/composants/IdentificationFenetre.java |
---|
New file |
0,0 → 1,118 |
package org.tela_botanica.client.composants; |
/* |
* Ext GWT - Ext for GWT |
* Copyright(c) 2007, 2008, Ext JS, LLC. |
* licensing@extjs.com |
* |
* http://extjs.com/license |
*/ |
import com.extjs.gxt.ui.client.event.ButtonEvent; |
import com.extjs.gxt.ui.client.event.ComponentEvent; |
import com.extjs.gxt.ui.client.event.KeyListener; |
import com.extjs.gxt.ui.client.event.SelectionListener; |
import com.extjs.gxt.ui.client.widget.Dialog; |
import com.extjs.gxt.ui.client.widget.button.Button; |
import com.extjs.gxt.ui.client.widget.button.StatusButtonBar; |
import com.extjs.gxt.ui.client.widget.form.TextField; |
import com.extjs.gxt.ui.client.widget.layout.FormLayout; |
import com.google.gwt.user.client.Timer; |
public class IdentificationFenetre extends Dialog { |
protected StatusButtonBar buttonBar; |
protected TextField<String> userName; |
protected TextField<String> password; |
protected Button reset; |
protected Button login; |
public IdentificationFenetre() { |
FormLayout layout = new FormLayout(); |
layout.setLabelWidth(90); |
layout.setDefaultWidth(155); |
setLayout(layout); |
setButtons(""); |
setIconStyle("user"); |
setHeading("Collections en ligne - Identification"); |
setModal(true); |
setBodyBorder(true); |
setBodyStyle("padding: 10px;background: none"); |
setWidth(300); |
setResizable(false); |
KeyListener keyListener = new KeyListener() { |
public void componentKeyUp(ComponentEvent event) { |
validate(); |
} |
}; |
userName = new TextField<String>(); |
userName.setMinLength(4); |
userName.setFieldLabel("Courriel"); |
userName.addKeyListener(keyListener); |
add(userName); |
password = new TextField<String>(); |
password.setMinLength(4); |
password.setPassword(true); |
password.setFieldLabel("Mot de passe"); |
password.addKeyListener(keyListener); |
add(password); |
setFocusWidget(userName); |
buttonBar = new StatusButtonBar(); |
setButtonBar(buttonBar); |
} |
@Override |
protected void createButtons() { |
reset = new Button("Réinitialiser"); |
reset.addSelectionListener(new SelectionListener<ButtonEvent>() { |
public void componentSelected(ButtonEvent ce) { |
userName.reset(); |
password.reset(); |
validate(); |
userName.focus(); |
} |
}); |
login = new Button("Valider"); |
//login.disable(); // Par défaut : dois être en mode disable |
login.addSelectionListener(new SelectionListener<ButtonEvent>() { |
public void componentSelected(ButtonEvent ce) { |
onSubmit(); |
} |
}); |
buttonBar.add(reset); |
buttonBar.add(login); |
} |
protected void onSubmit() { |
buttonBar.getStatusBar().showBusy("Chargement en cours ..."); |
buttonBar.disable(); |
Timer t = new Timer() { |
@Override |
public void run() { |
IdentificationFenetre.this.hide(); |
} |
}; |
t.schedule(2);// Par défaut : 2000 |
} |
protected boolean hasValue(TextField<String> field) { |
return field.getValue() != null && field.getValue().length() > 0; |
} |
protected void validate() { |
login.setEnabled(hasValue(userName) && hasValue(password) && password.getValue().length() > 3); |
} |
} |
/trunk/src/org/tela_botanica/client/modeles/Folder.java |
---|
File deleted |
\ No newline at end of file |
/trunk/src/org/tela_botanica/client/modeles/Institution.java |
---|
File deleted |
/trunk/src/org/tela_botanica/client/modeles/Configuration.java |
---|
New file |
0,0 → 1,51 |
package org.tela_botanica.client.modeles; |
import com.google.gwt.i18n.client.Dictionary; |
/** |
* Classe chargeant certains paramètres de configuration à partir d'un fichier |
* javascript (config.js) |
* |
* @author Aurélien PERONNET |
* |
*/ |
public class Configuration { |
/** |
* L'url de base du serveur jrest |
*/ |
private String serviceBaseUrl; |
/** |
* L'url de base du Carnet en Ligne |
*/ |
private String celUrl; |
/** |
* Constructeur sans argument |
*/ |
public Configuration() { |
// on utilise le dictionnaire d'internationalisation pour lire les variables du fichier javascript |
Dictionary configuration = Dictionary.getDictionary("configuration"); |
serviceBaseUrl = configuration.get("serviceBaseUrl"); |
celUrl = configuration.get("celUrl"); |
} |
/** |
* Accesseur pour l'url de base du serveur jrest |
* |
* @return une url de la forme http://emplacement_serveur/jrest |
*/ |
public String getServiceBaseUrl() { |
return serviceBaseUrl; |
} |
/** |
* Accesseur pour l'url de base du Carnet en Ligne |
* |
* @return une url de la forme http://emplacement_serveur/ |
*/ |
public String getCelUrl() { |
return celUrl; |
} |
} |
/trunk/src/org/tela_botanica/client/modeles/Structure.java |
---|
New file |
0,0 → 1,122 |
package org.tela_botanica.client.modeles; |
import java.io.Serializable; |
import java.util.Iterator; |
import java.util.Set; |
import com.extjs.gxt.ui.client.data.BaseModelData; |
import com.google.gwt.json.client.JSONObject; |
public class Structure extends BaseModelData implements Serializable { |
/** |
* Identifiant pour sérialisé l'objet... |
*/ |
private static final long serialVersionUID = 1L; |
/** |
* Constructeur vide |
* |
*/ |
public Structure() { |
} |
/** |
* Constructeur avec un objet JSON |
* |
* @param image |
*/ |
public Structure(JSONObject institution) { |
// l'objet JSON est une table de hachage |
Set<String> im = institution.keySet(); |
// Parcourt pour chaque clé |
for (Iterator<String> it = im.iterator(); it.hasNext();) { |
// Si elle est associée à une valeur, nous l'ajoutons |
String cle = it.next(); |
// Suppression de l'abréviation du champ. Inutile dans le contexte d'un objet |
String cleObjet = cle.replaceFirst("^cs_", ""); |
if (institution.get(cle).isString() != null) { |
String valeur = institution.get(cle).isString().stringValue(); |
this.set(cleObjet, valeur); |
} else { |
// Sinon, nous ajoutons la clé avec une valeur vide |
String valeur = " "; |
this.set(cleObjet, valeur); |
} |
} |
} |
public String getId() { |
return (String) renvoyerValeurCorrecte("id_structure"); |
} |
public String getNom() { |
return (String) renvoyerValeurCorrecte("nom"); |
} |
public String getDescription() { |
return (String) renvoyerValeurCorrecte("description"); |
} |
public String getAdresse01() { |
return (String) renvoyerValeurCorrecte("adresse_01"); |
} |
public String getCodePostal() { |
return (String) renvoyerValeurCorrecte("code_postal"); |
} |
public String getVille() { |
return (String) renvoyerValeurCorrecte("ville"); |
} |
public String getRegion() { |
return (String) renvoyerValeurCorrecte("region"); |
} |
public String getPays() { |
return (String) renvoyerValeurCorrecte("pays"); |
} |
public String getTelephone() { |
return (String) renvoyerValeurCorrecte("telephone"); |
} |
public String getFax() { |
return (String) renvoyerValeurCorrecte("fax"); |
} |
public String getCourriel() { |
return (String) renvoyerValeurCorrecte("courriel"); |
} |
public String getConditionAcces() { |
return (String) renvoyerValeurCorrecte("condition_acces"); |
} |
/** |
* Pour éviter que l'on traite des valeurs nulles à l'affichage on passe par |
* cette fonction qui retire les charactères nuls qui font planter |
* l'affichage, il ne faut pas utiliser get directement |
* |
* @param cle |
* @return la valeur associée à la clé |
*/ |
public String renvoyerValeurCorrecte(String cle) { |
if (this.get(cle) != null) { |
String valeur = this.get(cle); |
if (valeur.equals("null") || valeur == null) { |
return " "; |
} else { |
char nullChar = '\u0000'; |
String sNull = "" + nullChar; |
valeur = valeur.replaceAll(sNull, ""); |
return valeur; |
} |
} else { |
return " "; |
} |
} |
} |
/trunk/src/org/tela_botanica/client/modeles/ListeStructure.java |
---|
New file |
0,0 → 1,56 |
package org.tela_botanica.client.modeles; |
import java.util.LinkedHashMap; |
import com.google.gwt.json.client.JSONArray; |
import com.google.gwt.json.client.JSONObject; |
/** |
* Table de hachage composée d'informations sur les Structures, renvoyé par un objet de type DAO |
* La clé est le nom de l'entite + le nom de l'entite parente |
* |
* @author david delon |
* |
*/ |
public class ListeStructure extends LinkedHashMap<String, Structure> { |
/** |
* Identifiant pour sérialisé l'objet... |
*/ |
private static final long serialVersionUID = 2L; |
/** |
* Constructeur sans paramètres |
*/ |
public ListeStructure() { |
super(); |
} |
/** |
* Constructeur avec paramètre |
* @param taille la taille de la table de hachage |
*/ |
public ListeStructure(int taille) |
{ |
super(taille); |
} |
/** |
* Constructeur pour une liste d'institutions |
* @param dates |
*/ |
public ListeStructure(JSONArray institutions) |
{ |
super(institutions.size()) ; |
final int taillemax = institutions.size(); |
for (int i = 0; i < taillemax; i++) { |
JSONObject institutionCourante = institutions.get(i).isObject() ; |
if (institutionCourante != null) { |
Structure institution = new Structure(institutionCourante); |
this.put(institution.getId(), institution); |
} |
} |
} |
} |
/trunk/src/org/tela_botanica/client/modeles/ListeStructureAsyncDao.java |
---|
New file |
0,0 → 1,60 |
package org.tela_botanica.client.modeles; |
import java.util.ArrayList; |
import java.util.List; |
import org.tela_botanica.client.RegistreId; |
import org.tela_botanica.client.interfaces.Rafraichissable; |
import org.tela_botanica.client.vues.StructureDetailPanneauVue; |
import com.extjs.gxt.ui.client.Registry; |
import com.google.gwt.http.client.Request; |
import com.google.gwt.http.client.RequestBuilder; |
import com.google.gwt.http.client.RequestCallback; |
import com.google.gwt.http.client.RequestException; |
import com.google.gwt.http.client.Response; |
import com.google.gwt.json.client.JSONArray; |
import com.google.gwt.json.client.JSONParser; |
import com.google.gwt.json.client.JSONValue; |
public class ListeStructureAsyncDao { |
private ListeStructure institutions = null; |
private Rafraichissable rafraichissement = null; |
public ListeStructureAsyncDao(Rafraichissable r) { |
rafraichissement = r; |
} |
public void obtenirListeInstitution() { |
// Demande de toutes les structures |
String url = ((Configuration) Registry.get(RegistreId.CONFIG)).getServiceBaseUrl(); |
RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, url+"CoelStructureListe/"); |
try { |
rb.sendRequest(null, new RequestCallback() { |
public void onError(Request request, Throwable exception) { |
// TODO Auto-generated method stub |
} |
public void onResponseReceived(Request request, Response response) { |
final JSONValue responseValue = JSONParser.parse(response.getText()); |
// Si la requête est un succès, reception d'un tableau |
if (responseValue.isArray() != null) { |
final JSONArray reponse = responseValue.isArray(); |
// Transformation du tableau JSON réponse en ListeInstitution |
institutions = new ListeStructure(reponse); |
// et on met à jour le demandeur des données |
rafraichissement.rafraichir(institutions); |
} |
} |
}); |
} catch (RequestException e) { |
e.printStackTrace(); |
} |
} |
} |
/trunk/src/org/tela_botanica/client/modeles/Menu.java |
---|
New file |
0,0 → 1,33 |
package org.tela_botanica.client.modeles; |
import java.io.Serializable; |
import com.extjs.gxt.ui.client.data.BaseTreeModel; |
import com.extjs.gxt.ui.client.data.TreeModel; |
public class Menu extends BaseTreeModel<TreeModel> implements Serializable { |
public Menu() { |
} |
public Menu(String n) { |
set("nom", n); |
} |
public Menu(String nom, BaseTreeModel[] enfant) { |
this(nom); |
for (int i = 0; i < enfant.length; i++) { |
add(enfant[i]); |
} |
} |
public String getNom() { |
return (String) get("nom"); |
} |
public String toString() { |
return getNom(); |
} |
} |
/trunk/src/org/tela_botanica/public/Coel.html |
---|
17,6 → 17,9 |
<!-- Fichier CSS spécifique à l'application --> |
<link rel="stylesheet" type="text/css" href="Coel.css" /> |
<!-- Fichier JS de configuration spécifique à l'application --> |
<script type="text/javascript" language="javascript" src="config.js"></script> |
<!-- --> |
<!-- This script loads your compiled module. --> |
<!-- If you add any GWT meta tags, they must --> |
23,7 → 26,9 |
<!-- be added before this line. --> |
<!-- --> |
<script type="text/javascript" language="javascript" src="org.tela_botanica.Coel.nocache.js"></script> |
<link rel="stylesheet" type="text/css" href="css/ext-all.css" /> |
<!-- Fichier CSS spécifique à GXT --> |
<link rel="stylesheet" type="text/css" href="css/ext-all.css" /> |
</head> |
<!-- --> |
44,4 → 49,4 |
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe> |
</body> |
</html> |
</html> |
/trunk/src/org/tela_botanica/public/images/bg/hd-bg.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
/trunk/src/org/tela_botanica/public/images/bg/hd-bg.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+image/png |
\ No newline at end of property |
/trunk/src/org/tela_botanica/public/images/icones/LICENCE.txt |
---|
New file |
0,0 → 1,4 |
Source : http://www.famfamfam.com/lab/icons/silk/ |
Licence : Creative Commons Attribution 2.5 License < http://creativecommons.org/licenses/by/2.5/ > |
Voir tous les icônes : http://www.famfamfam.com/lab/icons/silk/previews/index_abc.png |
Fichier utilisés : ajouter.png, supprimer.png, application_formulaire_modifier.png |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/trunk/src/org/tela_botanica/public/images/icones/application_formulaire_modifier.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
/trunk/src/org/tela_botanica/public/images/icones/application_formulaire_modifier.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+image/png |
\ No newline at end of property |
/trunk/src/org/tela_botanica/public/images/icones/supprimer.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
/trunk/src/org/tela_botanica/public/images/icones/supprimer.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+image/png |
\ No newline at end of property |
/trunk/src/org/tela_botanica/public/images/icones/ajouter.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
/trunk/src/org/tela_botanica/public/images/icones/ajouter.png |
---|
New file |
Property changes: |
Added: svn:mime-type |
+image/png |
\ No newline at end of property |
/trunk/src/org/tela_botanica/public/Coel.php |
---|
New file |
0,0 → 1,52 |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
<!-- The HTML 4.01 Transitional DOCTYPE declaration--> |
<!-- above set at the top of the file will set --> |
<!-- the browser's rendering engine into --> |
<!-- "Quirks Mode". Replacing this declaration --> |
<!-- with a "Standards Mode" doctype is supported, --> |
<!-- but may lead to some differences in layout. --> |
<html> |
<head> |
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> |
<!-- --> |
<!-- Any title is fine --> |
<!-- --> |
<title>Coel<?php echo ' - PHP v'.phpversion();?></title> |
<!-- Fichier CSS spécifique à l'application --> |
<link rel="stylesheet" type="text/css" href="Coel.css" /> |
<!-- Fichier JS de configuration spécifique à l'application --> |
<script type="text/javascript" language="javascript" src="config.js"></script> |
<!-- --> |
<!-- This script loads your compiled module. --> |
<!-- If you add any GWT meta tags, they must --> |
<!-- be added before this line. --> |
<!-- --> |
<script type="text/javascript" language="javascript" src="org.tela_botanica.Coel.nocache.js"></script> |
<!-- Fichier CSS spécifique à GXT --> |
<link rel="stylesheet" type="text/css" href="css/ext-all.css" /> |
</head> |
<!-- --> |
<!-- The body can have arbitrary html, or --> |
<!-- you can leave the body empty if you want --> |
<!-- to create a completely dynamic UI. --> |
<!-- --> |
<body> |
<div id="loading"> |
<div class="loading-indicator"> |
<img src="images/default/shared/large-loading.gif" width="32" height="32" style="margin-right:8px;float:left;vertical-align:top;"/> |
COEL v1.0 |
<a href="http://extjs.com"></a><br /> |
<span id="loading-msg">Chargement de l'application Collections en Ligne...</span> |
</div> |
</div> |
<!-- OPTIONAL: include this if you want history support --> |
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe> |
</body> |
</html> |
/trunk/src/org/tela_botanica/public/Coel.css |
---|
1,40 → 1,141 |
/** Les CSS de l'application COEL */ |
* { |
margin: 0px; |
padding: 0px; |
} |
margin: 0px; |
padding: 0px;} |
/* #------------------------------------------------------------------------------------------------------# */ |
/* CHARGEMENT APPLICATION */ |
/* #------------------------------------------------------------------------------------------------------# */ |
#loading { |
position: absolute; |
left: 45%; |
top: 40%; |
margin-left: -45px; |
padding: 2px; |
z-index: 20001; |
height: auto; |
border: 1px solid #ccc; |
} |
position: absolute; |
left: 45%; |
top: 40%; |
margin-left: -45px; |
padding: 2px; |
z-index: 20001; |
height: auto; |
border: 1px solid #ccc;} |
#loading a { |
color: #225588; |
} |
color: #225588;} |
#loading .loading-indicator { |
background: white; |
color: #444; |
font: bold 13px tahoma, arial, helvetica; |
padding: 10px; |
margin: 0; |
height: auto; |
} |
background: white; |
color: #444; |
font: bold 13px tahoma, arial, helvetica; |
padding: 10px; |
margin: 0; |
height: auto;} |
#loading .loading-indicator img { |
margin-right:8px; |
float:left; |
vertical-align:top; |
} |
margin-right:8px; |
float:left; |
vertical-align:top;} |
#loading-msg { |
font: normal 10px arial, tahoma, sans-serif;} |
#loading-msg { |
font: normal 10px arial, tahoma, sans-serif; |
} |
/* #------------------------------------------------------------------------------------------------------# */ |
/* ENTÊTE */ |
/* #------------------------------------------------------------------------------------------------------# */ |
#coel-entete { |
height:100px; |
background:#1E4176 url(images/bg/hd-bg.png) repeat-x scroll 0pt; |
border:0pt none; |
padding-left:3px;} |
#coel-titre { |
color:white; |
font-family:tahoma, arial, sans-serif; |
font-size:16px; |
font-size-adjust:none; |
font-stretch:normal; |
font-style:normal; |
font-variant:normal; |
font-weight:normal; |
line-height:normal; |
padding:6 0 8 6px;} |
/* #------------------------------------------------------------------------------------------------------# */ |
/* PANNEAU DÉTAIL */ |
/* #------------------------------------------------------------------------------------------------------# */ |
.coel-detail { |
height: 55px; |
background-color: #ddd; |
border-bottom: 1px solid silver;} |
.coel-detail h1 { |
font-weight: bold; |
font-size: 12px; |
padding: 5 0 2 5px;} |
.coel-detail h2 { |
font-size: 11px; |
font-weight: normal; |
padding: 0 5 0 5px;} |
.coel-detail h3 { |
font-size: 11px; |
font-weight: normal; |
padding: 0 5 5 5px;} |
.coel-detail-body { |
padding: 12px;} |
/* Liste de définition : style provenant de pompage.net : http://pompage.net/pompe/listesdefinitions/ */ |
dl.hb_affichage_tabulaire { |
width: 61em;} |
.hb_affichage_tabulaire dt { |
width: 20em; |
float: left; |
margin: 0; |
padding: .2em;} |
/* hack de commentaire avec un antislash pour ie5 mac \*/ |
dt { |
clear: both;} |
/* end hack */ |
.hb_affichage_tabulaire dd { |
float: left; |
z-index:1; |
width: 40em; |
margin: 0; |
padding: .2em;} |
h2, .parent, .hb_espace, .hb_ligne { |
clear: both;} |
.hb_titre_en_ligne { |
display: inline; |
padding-top: 1em;} |
#hb_renseignement_admin{ |
max-width:650px; |
float:left;} |
#hb_logo { |
float:right;} |
dt, label { |
font-weight: bold;} |
form ul { |
list-style-type: none;} |
.hb_img_icone { |
border:0; |
width:9px; |
height:9px;} |
.hb_img_fermer { |
border:0; |
width:9px; |
height:9px;} |
.hb_ligne { |
border: .2em dotted; |
width:4em;} |
.hb_plier_deplier td{ |
padding:0; |
margin:0; |
text-align:left; |
height:12px; |
border-width:0;} |
.hb_arborescence td{ |
padding:0; |
margin: -5px 0 0 0; |
text-align:left; |
vertical-align:top; |
border-width:0;} |
.pair{ |
background-color: #FAD2C6;} |
/* #------------------------------------------------------------------------------------------------------# */ |
/* ÎCONES */ |
/* #------------------------------------------------------------------------------------------------------# */ |
.icone-ajouter { |
background: url(images/icones/ajouter.png) no-repeat center left !important;} |
.icone-modifier { |
background: url(images/icones/application_formulaire_modifier.png) no-repeat center left !important;} |
.icone-supprimer { |
background: url(images/icones/supprimer.png) no-repeat center left !important;} |
/trunk/src/org/tela_botanica/public/config.js |
---|
New file |
0,0 → 1,4 |
var configuration = { |
celUrl:"http://www.tela-botanica.org/cel/www/org.tela_botanica.Cel/Cel.html", |
serviceBaseUrl:"http://localhost/jrest/" |
}; |