Wittyshare  0.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
WsFormConfig.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-Today Guy Deleeuw
3  *
4  * See the LICENSE file for terms of use.
5 */
6 
7 #include <Wt/WApplication>
8 #include <Wt/WPanel>
9 #include <Wt/WTable>
10 #include <Wt/WText>
11 #include <Wt/WTheme>
12 #include <Wt/WIntValidator>
13 #include <Wt/WRegExpValidator>
14 
15 #include <gdcore/gdCore.h>
16 
17 #include "WsApplication.h"
18 #include "WsFormConfig.h"
19 #include "WsErrorPage.h"
20 
21 using namespace Wt;
22 
23 WsFormConfig::WsFormConfig(NodePtr pNode, WsModulesLoader& rMl, WContainerWidget* parent)
24  : WContainerWidget(parent), m_pNode(pNode), m_ml(rMl), m_pAuthor(0), m_pShortDescEditor(0), m_pShortDescTextArea(0), m_pCBInMenu(0), m_pCBInView(0), m_pFhtmlEditor(0), m_pInitPage(0), m_bUseTextArea(true), m_pSave(0), m_pLock(0), m_pTimer(0), m_pTimerTick(0), m_timeLockLeft(0)
25 {
26  // if ( WsLayoutProperties::instance()->get("global", "by_object_stylesheet", "false") == "true" )
27  if ( WString::tr("byObjectStyleSheet").narrow() == "true" )
28  wApp->useStyleSheet(wApp->theme()->resourcesUrl() + "wittyshare/Css/WsFormConfig.css");
29  addStyleClass("WsFormConfig");
30  /*
31  * in properties
32  * =============
33  - name, for renaming a node
34  - publish_date
35  - author
36  - short_desc
37  - display_name
38  - in_menu
39  - in_view
40  - sort
41  - sort index
42  - inherit_rights_from_parent
43  -
44  */
45  WsUser* pUser = WsApp->wsUser();
46  //Test if user has write access
47  if(pUser->getPermissions(pNode->getPath().string()) != GlobalConfig::ReadWrite)
48  {
49  addWidget(new WsErrorPage(WsErrorPage::Forbidden,pNode->getPath().string(), pUser));
50  return;
51  }
52  WTable* pTable = new WTable();
53  int iRow = 0;
54  // Les dates sont sockées en string format time_t TODO : add try/catch
55  // Publish Date
56  WDateTime dt(WDateTime::currentDateTime());
57  std::string sDateTime = pNode.get()->getProperties().get()->get("global", "publish_date", boost::lexical_cast<std::string>(dt.toTime_t()));
58  m_wDateTime.setTime_t(boost::lexical_cast<time_t>(sDateTime));
59  Wt::WRegExpValidator* validatorName = new Wt::WRegExpValidator("[a-zA-Z0-9._& ]{2,48}");
60  new WText("(new ?) name", pTable->elementAt(iRow, 0));
61  m_sName = pNode.get()->getName();
62  m_pName = new WLineEdit(WString::fromUTF8(m_sName), pTable->elementAt(iRow, 2));
63  m_pName->setValidator(validatorName);
64  m_pName->setTextSize(48);
65  if ( pNode.get()->isDirectory() ) {
66  new WText("Initial page", pTable->elementAt(iRow, 4));
67  m_sInitPage = pNode.get()->getProperties().get()->get("global", "initial_page", "");
68  m_pInitPage = new WLineEdit(WString::fromUTF8(m_sInitPage), pTable->elementAt(iRow, 6));
69  m_pInitPage->setTextSize(32);
70  }
71  iRow++;
72  new WText("Publish Date", pTable->elementAt(iRow, 0));
73  m_pDatePicker = new WDatePicker(pTable->elementAt(iRow, 2));
74  m_pDatePicker->setFormat("yyyy-MM-dd");
75  m_pDatePicker->setDate(m_wDateTime.date());
76  // Display name : pNode->getDisplayName() return the pNode->getName if the display_name is empty.
77  new WText("Display name", pTable->elementAt(iRow, 4));
78  // std::string ds = pNode->getProperties().get()->get("global", "display_name", pNode->getName());
79  m_sDisplayName = pNode.get()->getDisplayName(true);
80  m_pDisplayName = new WLineEdit(WString::fromUTF8(m_sDisplayName), pTable->elementAt(iRow, 6));
81  m_pDisplayName->setTextSize(60);
82  iRow++;
83  // TODO : get all possible author ?
84  std::string curUser = pUser->getFirstName() + " " + pUser->getSurname();
85  m_sAuthor = pNode.get()->getProperties().get()->get("global", "author", curUser);
86  new WText("Author", pTable->elementAt(iRow, 0));
87  m_pAuthor = new WLineEdit(WString::fromUTF8(m_sAuthor), pTable->elementAt(iRow, 2));
88  m_pAuthor->setTextSize(30);
89  std::string sSortNumber = pNode.get()->getProperties().get()->get("global", "sort_number", "-1");
90  new WText("Sort Number", pTable->elementAt(iRow, 4));
91  m_lSortNumber = boost::lexical_cast<long>(sSortNumber);
92  m_pSortNumber = new WLineEdit(WString::fromUTF8(sSortNumber), pTable->elementAt(iRow, 6));
93  m_pSortNumber->setTextSize(10);
94  WIntValidator* validator = new WIntValidator(-1, 9999);
95  validator->setMandatory(true);
96  m_pSortNumber->setValidator(validator);
97  iRow++;
98  m_pCBInheritRights = new WCheckBox("Inherit parent rights", pTable->elementAt(iRow, 0));
99  std::string sInheritRights = pNode.get()->getProperties().get()->get("global", "inherit_rights_from_parent", "false");
100  if ( sInheritRights == "true" )
101  m_pCBInheritRights->setCheckState(Wt::Checked);
102  m_bInheritRights = m_pCBInheritRights->checkState();
103  m_pCBInMenu = new WCheckBox("In menu", pTable->elementAt(iRow, 2));
104  // TODO : Il faut activer ce qui apparait dans les menus ?
105  std::string sInMenu = pNode.get()->getProperties().get()->get("global", "in_menu", "false");
106  if ( sInMenu == "true" )
107  m_pCBInMenu->setCheckState(Wt::Checked);
108  m_binMenu = m_pCBInMenu->checkState();
109  std::string sSort = pNode.get()->getProperties().get()->get("global", "sort", "false");
110  m_pCBSort = new WCheckBox("Sort", pTable->elementAt(iRow, 4));
111  if ( sSort == "true" )
112  m_pCBSort->setCheckState(Wt::Checked);
113  m_bSort = m_pCBSort->checkState();
114  m_pCBInView = new WCheckBox("In view", pTable->elementAt(iRow, 6));
115  std::string sInView = pNode.get()->getProperties().get()->get("global", "in_view", "true");
116  if ( sInView == "true" )
117  m_pCBInView->setCheckState(Wt::Checked);
118  m_binView = m_pCBInView->checkState();
119  iRow++;
120  new WText("Template", pTable->elementAt(iRow, 0));
121  m_pCBBTemplates = new Wt::WComboBox(pTable->elementAt(iRow, 2));
122  std::string sTemplate = pNode.get()->getProperties().get()->get("global", "template", "stdSubPage.tpl");
123  // TODO : boucler avec les droits ? sur /.config/templates/*.tpl
124  std::vector<std::string> vTemplates;
125  vTemplates.push_back("root.tpl");
126  vTemplates.push_back("stdSubPage.tpl");
127  for ( int countTemplates = 0; countTemplates < vTemplates.size(); ++countTemplates) {
128  m_pCBBTemplates->addItem(vTemplates[countTemplates]);
129  if ( vTemplates[countTemplates] == sTemplate ) {
130  m_pCBBTemplates->setCurrentIndex(countTemplates);
131  m_sTemplate = vTemplates[countTemplates];
132  }
133  }
134  iRow++;
135  m_sShortDesc = pNode.get()->getProperties().get()->get("global", "short_description", "");
136  if ( m_bUseTextArea ) {
137  m_pShortDescTextArea = new WTextArea(m_sShortDesc);
138  m_pShortDescTextArea->resize(WLength(100, WLength::Percentage), WLength(300));
139  // m_pShortDescTextArea->setOverflow(WContainerWidget::OverflowAuto);
140  } else {
141  m_pShortDescEditor = new gdFHtmlEditor(m_sShortDesc, false);
142  m_pShortDescEditor->resize(WLength(100, WLength::Percentage), WLength(300));
143  m_pShortDescEditor->setOverflow(WContainerWidget::OverflowAuto);
144  }
145  iRow++;
146  WPushButton* pButCancel = new WPushButton("Cancel");
147  pButCancel->clicked().connect(SLOT(this, WsFormConfig::doCancel));
148  addWidget(pButCancel);
149  m_pSave = new WPushButton("Save");
150  m_pSave->clicked().connect(SLOT(this, WsFormConfig::doSave));
151  if (!pNode->isDirectory()) {
152  m_pLock = new WPushButton("Extend the lock");
153  m_pLock->clicked().connect(SLOT(this, WsFormConfig::doLock));
154  addWidget(m_pLock);
155  doLock();
156  }
157  addWidget(m_pSave);
158  WContainerWidget* pCW = new WContainerWidget();
159  pCW->addWidget(pTable);
160  pCW->addWidget(new WText("<b>Short Description</b>"));
161  if ( m_bUseTextArea )
162  pCW->addWidget(m_pShortDescTextArea);
163  else
164  pCW->addWidget(m_pShortDescEditor);
165  std::string title = "Properties of " + pNode.get()->getPath().string();
166  WPanel* pPanel = new WPanel();
167  pPanel->setTitle(title);
168  pPanel->setCentralWidget(pCW);
169  pPanel->setCollapsible(true);
170  // pPanel->setOverflow(Wt::WContainerWidget::OverflowAuto);
171  addWidget(pPanel);
172  pPanel->expand();
173  //pCW->addWidget(new WText("Modules specifics options"));
174  for (int iModule = 0; iModule < m_ml.modules().size(); iModule++) {
175  WsModule* curModule = m_ml.modules()[iModule]->module;
176  if ( !curModule->isLoaded() ) continue;
177  WsEditorWidget* w = curModule->createEditor();
178  if ( w ) {
179  m_vEditorWidget.push_back(w);
180  WPanel* pPanel2 = new WPanel();
181  pPanel2->setTitle(curModule->moduleName());
182  pPanel2->setCentralWidget(w);
183  pPanel2->setCollapsible(true);
184  pPanel2->expand();
185  pCW->addWidget(pPanel2);
186  }
187  }
188 }
189 
191 { }
192 
193 void WsFormConfig::setEditorFhtml(gdFHtmlEditor* pFhtmlEditor)
194 {
195  m_pFhtmlEditor = pFhtmlEditor;
196 }
197 
199 {
200  WsApp->wsUser()->putLock(m_pNode->getPath().string());
201  wApp->setInternalPath(m_pNode->getPath().string(), true);
202 }
203 
205 {
206  m_timeLockLeft = WsApp->wsUser()->getLock(m_pNode->getPath().string());
207  if (m_timeLockLeft <= 0) {
208  /* node is locked */
209  m_pSave->hide();
210  m_pLock->hide();
211  std::string id = "";
212  /* get the uid of the locked */
213  WsApp->wsUser()->isLocked(m_pNode->getPath().string(), id);
214  addWidget(new WText("<font color='red'>The file is currently locked by \"" + id + "\". Please try again later</font>"));
215  return;
216  }
217  m_pLock->hide();
218  m_pSave->show();
219  if (m_pTimer) {
220  m_pTimer->stop();
221  delete m_pTimer;
222  }
223  m_pTimer = new Wt::WTimer();
224  m_pTimer->setInterval(m_timeLockLeft * 1000);
225  m_pTimer->timeout().connect(this, &WsFormConfig::doLockEnd);
226  m_pTimer->start();
228  if (m_pTimerTick != 0) {
229  m_pTimerTick->stop();
230  delete m_pTimerTick;
231  }
232  m_pTimerTick = new Wt::WTimer();
233  m_pTimerTick->setInterval(60 * 1000);
234  m_pTimerTick->timeout().connect(this, &WsFormConfig::doUpdateTimerLock);
235  m_pTimerTick->start();
236 }
237 
239 {
240  m_pTimer->stop();
241  m_pTimerTick->stop();
242  m_pSave->hide();
243  m_pLock->hide();
244  WMessageBox::show("Warning", "The file lock is released. Please copy your data and refresh the page to continue editing", Ok);
245 }
246 
248 {
249  if (m_timeLockLeft < 600)
250  m_pLock->show();
251  std::string tl = boost::lexical_cast<std::string>(m_timeLockLeft / 60);
252  m_pSave->setText("Save..(" + tl + " min left)");
253  m_timeLockLeft -= 60;
254 }
255 
257 {
258  if (!m_pNode->isDirectory()) {
259  m_timeLockLeft = WsApp->wsUser()->getLock(m_pNode->getPath().string());
260  if (m_timeLockLeft <= 0) {
261  doLockEnd();
262  return;
263  }
264  }
265  if ( !m_pName->validate() ) return;
266  if ( !m_pSortNumber->validate() ) return;
267  bool bUpdated = false;
268  WDateTime dt(m_pDatePicker->date(), WTime::currentServerTime());
269  std::string sDateTime = dt.toString("yyyy-MM-dd hh:mm:ss").narrow();
270  std::string sName = m_pName->text().toUTF8();
271  if ( sName.size() < 2 ) return;
272  std::string sInitPage = "";
273  if ( m_pInitPage )
274  sInitPage = m_pInitPage->text().toUTF8();
275  std::string sDisplayName = m_pDisplayName->text().toUTF8();
276  std::string sAuthor = m_pAuthor->text().toUTF8();
277  std::string sInMenu = (m_pCBInMenu->checkState() == Wt::Checked ? "true" : "false");
278  std::string sInView = (m_pCBInView->checkState() == Wt::Checked ? "true" : "false");
279  std::string sShortDesc;
280  if ( m_bUseTextArea )
281  sShortDesc = m_pShortDescTextArea->text().toUTF8();
282  else
283  sShortDesc = m_pShortDescEditor->text().toUTF8();
284  std::string sSort = (m_pCBSort->checkState() == Wt::Checked ? "true" : "false");
285  std::string sSortNumber = m_pSortNumber->text().narrow();
286  std::string sInheritRights = (m_pCBInheritRights->checkState() == Wt::Checked ? "true" : "false");
287  std::string sTemplate = m_pCBBTemplates->currentText().toUTF8();
288  gdcore_string_erase_right(sDisplayName, ' ');
289  gdcore_string_erase_left(sDisplayName, ' ');
290  gdcore_string_erase_right(sAuthor, ' ');
291  gdcore_string_erase_left(sAuthor, ' ');
292  for (int iModule = 0; iModule < m_vEditorWidget.size(); ++iModule) {
293  m_vEditorWidget[iModule]->saveEditor();
294  }
295  WsUser* pUser = WsApp->wsUser();
296  if ( m_wDateTime != dt ) {
297  m_pNode->getProperties().get()->set("global", "publish_date", boost::lexical_cast<std::string>(dt.toTime_t()));
298  bUpdated = true;
299  }
300  if ( m_pNode->isDirectory() ) {
301  if ( m_sInitPage != sInitPage )
302  m_pNode->getProperties().get()->set("global", "initial_page", sInitPage);
303  bUpdated = true;
304  }
305  if ( m_sDisplayName != sDisplayName ) {
306  m_pNode->getProperties().get()->set("global", "display_name", sDisplayName);
307  bUpdated = true;
308  }
309  if ( m_sAuthor != sAuthor ) {
310  m_pNode->getProperties().get()->set("global", "author", sAuthor);
311  bUpdated = true;
312  }
313  if ( m_binMenu != m_pCBInMenu->checkState() ) {
314  m_pNode->getProperties().get()->set("global", "in_menu", sInMenu);
315  bUpdated = true;
316  }
317  if ( m_binView != m_pCBInView->checkState() ) {
318  m_pNode->getProperties().get()->set("global", "in_view", sInView);
319  bUpdated = true;
320  }
321  if ( sTemplate != m_sTemplate ) {
322  m_pNode->getProperties().get()->set("global", "template", sTemplate);
323  bUpdated = true;
324  }
325  if ( m_sShortDesc != sShortDesc ) {
326  m_pNode->getProperties().get()->set("global", "short_description", sShortDesc);
327  bUpdated = true;
328  }
329  if ( m_bSort != m_pCBSort->checkState() ) {
330  m_pNode->getProperties().get()->set("global", "sort", sSort);
331  bUpdated = true;
332  }
333  if ( m_lSortNumber != boost::lexical_cast<long>(sSortNumber) ) {
334  m_pNode->getProperties().get()->set("global", "sort_number", sSortNumber);
335  bUpdated = true;
336  }
337  if ( m_bInheritRights != m_pCBInheritRights->checkState() ) {
338  m_pNode->getProperties().get()->set("global", "inherit_rights_from_parent", sInheritRights);
339  bUpdated = true;
340  }
341  if ( bUpdated )
342  pUser->saveProperties(m_pNode->getProperties().get(), m_pNode->getPath().string());
343  if ( m_pFhtmlEditor ) {
344  wApp->log("notice") << "WsFormConfig::doSave() fhtml file = " << m_pNode->getFullPath(); // << " text = " << m_pFhtmlEditor->text().toUTF8();
345  if (! pUser->writeFile(m_pNode->getPath().string(), m_pFhtmlEditor->text().toUTF8().c_str()))
346  wApp->log("notice") << "WsFormConfig::doSave() cannot open " << m_pNode->getFullPath();
347  }
348  std::string oldName = m_pNode->getPath().string();
349  std::string newName = m_pNode->getPath().parent_path().string();
350  if ( newName != "/" ) newName += "/";
351  newName += sName;
352  wApp->log("notice") << "WsFormConfig::doSave() rename oldName = " << oldName << " newName " << newName;
353  if ( m_sName != sName )
354  pUser->renameNode(oldName, newName);
355  // wApp->setInternalPath(m_pNode->getPath().string(), true);
356  WsApp->wsUser()->putLock(m_pNode->getPath().string());
357  wApp->setInternalPath(newName, true);
358 }
359 
void setEditorFhtml(gdFHtmlEditor *pFhtmlEditor)
Wt::WLineEdit * m_pAuthor
Definition: WsFormConfig.h:48
boost::shared_ptr< WsAbstractNode > NodePtr
std::vector< WsEditorWidget * > m_vEditorWidget
Definition: WsFormConfig.h:44
int getPermissions(const std::string &p)
return the permissions on specific node
Definition: WsUser.cpp:81
const std::vector< WsModuleLoader * > & modules()
const int ReadWrite
std::string m_sShortDesc
Definition: WsFormConfig.h:75
std::string m_sTemplate
Definition: WsFormConfig.h:72
Wt::WCheckBox * m_pCBInMenu
Definition: WsFormConfig.h:52
bool m_bInheritRights
Definition: WsFormConfig.h:78
std::string m_sDisplayName
Definition: WsFormConfig.h:70
int saveProperties(WsNodeProperties *props, const std::string &path)
save the properties of the node on disk. The user must have access and edit rights for the node...
Definition: WsUser.cpp:156
Wt::WDateTime m_wDateTime
Definition: WsFormConfig.h:67
Wt::WTimer * m_pTimer
Definition: WsFormConfig.h:61
int writeFile(const std::string path, const std::string &text)
writes the text to the file
Definition: WsUser.cpp:161
int m_timeLockLeft
Definition: WsFormConfig.h:63
NodePtr m_pNode
Definition: WsFormConfig.h:42
virtual WsEditorWidget * createEditor(Wt::WContainerWidget *parent=0) const =0
Create the contents for an editor (create a view of options).
Interface that provides differents methods for accessing the FsTree as well as other features...
Definition: WsUser.h:33
bool m_bUseTextArea
Definition: WsFormConfig.h:79
std::string m_sName
Definition: WsFormConfig.h:68
Wt::WTimer * m_pTimerTick
Definition: WsFormConfig.h:62
Wt::WCheckBox * m_pCBInView
Definition: WsFormConfig.h:53
std::string m_sAuthor
Definition: WsFormConfig.h:71
Wt::WLineEdit * m_pName
Definition: WsFormConfig.h:45
const std::string & moduleName() const
Definition: WsOption.cpp:100
bool isLoaded()
Definition: WsModule.cpp:55
const std::string & getFirstName() const
return the name of the person
Definition: WsUser.cpp:66
WsModulesLoader & m_ml
Definition: WsFormConfig.h:43
Wt::WCheckBox * m_pCBSort
Definition: WsFormConfig.h:54
Wt::WTextArea * m_pShortDescTextArea
Definition: WsFormConfig.h:51
const std::string & getSurname() const
return the surname of the person
Definition: WsUser.cpp:61
void doUpdateTimerLock()
Wt::WLineEdit * m_pInitPage
Definition: WsFormConfig.h:46
#define WsApp
Define a shortcut to the application instance.
Definition: WsApplication.h:62
Wt::WPushButton * m_pSave
Definition: WsFormConfig.h:59
std::string m_sInitPage
Definition: WsFormConfig.h:69
Wt::WCheckBox * m_pCBInheritRights
Definition: WsFormConfig.h:57
gdFHtmlEditor * m_pShortDescEditor
Definition: WsFormConfig.h:50
gdFHtmlEditor * m_pFhtmlEditor
Definition: WsFormConfig.h:55
int renameNode(const string &path, const string &newPath)
renames a node In case of a WsDirNode, all the contents of the directory and the directory will be mo...
Definition: WsUser.cpp:120
Wt::WDatePicker * m_pDatePicker
Definition: WsFormConfig.h:49
long m_lSortNumber
Definition: WsFormConfig.h:77
Wt::WComboBox * m_pCBBTemplates
Definition: WsFormConfig.h:58
Wt::WLineEdit * m_pDisplayName
Definition: WsFormConfig.h:47
Wt::WPushButton * m_pLock
Definition: WsFormConfig.h:60
WsFormConfig(NodePtr pNode, WsModulesLoader &rMl, Wt::WContainerWidget *parent=0)
Wt::WLineEdit * m_pSortNumber
Definition: WsFormConfig.h:56