Commit b6728f6d authored by Mal's avatar Mal

Small formatting and bug fixes. Started new Roster module.

parent 5620b2f6
...@@ -88,7 +88,8 @@ class Comment extends Base { ...@@ -88,7 +88,8 @@ class Comment extends Base {
} }
public function CanAdd($page) { public function CanAdd($page) {
return true; // Can only have one comment module on a page.
return !$this->AlreadyOnPage("comment", $page);
} }
public function CanEdit($id) { public function CanEdit($id) {
......
...@@ -117,7 +117,7 @@ class Detail extends Base { ...@@ -117,7 +117,7 @@ class Detail extends Base {
} }
public function Factory($fn) { public function Factory($fn) {
if ($fn == "AllUsers") return $this->AllUsers();
} }
public function Group() { public function Group() {
...@@ -179,6 +179,25 @@ class Detail extends Base { ...@@ -179,6 +179,25 @@ class Detail extends Base {
// Private functions below here //////////////////////////////////////////// // Private functions below here ////////////////////////////////////////////
private function AllUsers() {
$object = array();
$mysqli = connect_db();
$query = 'SELECT user, first, last, phone FROM user_detail';
if ($result = $mysqli->query($query)) {
while ($detail = $result->fetch_assoc()) {
$object[$detail["user"]] = array("first" => $detail["first"],
"last" => $detail["last"],
"phone" => $detail["phone"]);
}
$result->close();
}
else {
$this->Log('Detail->AllUsers: '.$mysqli->error);
}
$mysqli->close();
return $object;
}
} }
?> ?>
\ No newline at end of file
...@@ -205,6 +205,8 @@ class Invoice extends Base { ...@@ -205,6 +205,8 @@ class Invoice extends Base {
} }
public function CanAdd($page) { public function CanAdd($page) {
// Need admin privileges to add the invoice module.
if (!$this->user->canEditSite) return false;
return true; return true;
} }
......
...@@ -64,10 +64,9 @@ class Purchase extends Base { ...@@ -64,10 +64,9 @@ class Purchase extends Base {
$object["outstanding"] = $object["outstanding"] =
(object)$this->AllOutstanding($payment_totals, strtotime("-24 hours")); (object)$this->AllOutstanding($payment_totals, strtotime("-24 hours"));
// TODO: This assumes that any purchases entered in the last 6 days // Only show purchases from the last 24 hours, as these are the only
// should be shown, ie don't want to show purchases from last week, // ones that can be changed in UpdateData below.
// but the time frame for showing purchases should be configurable. $since_last_week = strtotime("-24 hours");
$since_last_week = strtotime("-6 days");
// Cast to object required for json in case of an empty array. // Cast to object required for json in case of an empty array.
$object["data"] = (object)$this->AllData($since_last_week, true); $object["data"] = (object)$this->AllData($since_last_week, true);
// Return milliseconds for use with javascript Date object. // Return milliseconds for use with javascript Date object.
......
<?php
// Dobrado Content Management System
// Copyright (C) 2012 Malcolm Blaney
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
class Roster extends Base {
public function Add($id) {
}
public function Callback() {
$object = array();
$mysqli = connect_db();
$action = $mysqli->escape_string($_POST["action"]);
if ($action == "list") {
$object = $this->Show();
}
else if ($action == "submit") {
$name = $mysqli->escape_string($_POST["name"]);
$timestamp = (int)$mysqli->escape_string($_POST["timestamp"]) / 1000;
if ($name === "") {
$object["error"] = "No username given";
}
else if ($timestamp === "") {
$object["error"] = "No date given";
}
else {
$query = 'INSERT INTO roster VALUES ("'.$name.'","'.$timestamp.'")';
if (!$mysqli->query($query)) {
$this->Log('Roster->Callback 1:'.$mysqli->error);
}
$object = $this->Show();
}
}
else if ($action == "remove") {
$name = $mysqli->escape_string($_POST["name"]);
$timestamp = (int)$mysqli->escape_string($_POST["timestamp"]) / 1000;
if ($name === "") {
$object["error"] = "No username given";
}
else if ($timestamp === "") {
$object["error"] = "No date given";
}
else {
$query = 'DELETE FROM roster WHERE user="'.$name.'" AND timestamp="'.
$timestamp.'"';
if (!$mysqli->query($query)) {
$this->Log('Roster->Callback 2:'.$mysqli->error);
}
$object = $this->Show();
}
}
$mysqli->close();
return $object;
}
public function CanAdd($page) {
// Need admin privileges to add the payment module.
if (!$this->user->canEditSite) return false;
// Can only have one roster module on a page.
return !$this->AlreadyOnPage("roster", $page);
}
public function CanEdit($id) {
return true;
}
public function CanRemove($id) {
return true;
}
public function Content($id) {
return '<form id="roster-form">'.
'<div class="form-spacing">'.
'<label for="roster-name-input">Username:</label>'.
'<input id="roster-name-input" type="text" size="15" maxlength="100">'.
'</div>'.
'<div class="form-spacing">'.
'<label for="roster-date-input">Date:</label>'.
'<input id="roster-date-input" type="text" size="15" maxlength="50">'.
'</div>'.
'<button class="remove">remove</button>'.
'<button class="submit">submit</button>'.
'</form>';
}
public function Copy($id, $old_owner, $old_id) {
}
public function Factory($fn) {
}
public function Group() {
}
public function IncludeScript() {
return true;
}
public function Install($path) {
// Append dobrado.roster.js to the existing dobrado.js file.
// Note that the module is only available when logged in.
$this->AppendScript($path, "dobrado.roster.js", false);
$mysqli = connect_db();
$query = 'CREATE TABLE IF NOT EXISTS roster ('.
'user VARCHAR(50) NOT NULL,'.
'timestamp INT(10) UNSIGNED NOT NULL,'.
'PRIMARY KEY(user, timestamp)'.
') ENGINE=MyISAM';
if (!$mysqli->query($query)) {
$this->Log('Roster->Install: '.$mysqli->error);
}
$mysqli->close();
$site_style = array('"","#roster-form","background-color","#eeeeee"',
'"","#roster-form","border","1px solid #aaaaaa"',
'"","#roster-form","border-radius","2px"',
'"","#roster-form","padding","5px"',
'"","#roster-form label","width","6em"',
'"","#roster-form .submit","float","right"');
$this->AddSiteStyle($site_style);
}
public function Placement() {
return "middle";
}
public function Remove($id) {
}
public function SetContent($id, $us_content) {
}
public function Update() {
// This is called when the version of the module is updated,
// to provide a way to update or modify tables etc..
}
public function UpdateScript($path) {
$this->AppendScript($path, "dobrado.roster.js", false);
}
// Private functions below here ////////////////////////////////////////////
private function Show() {
$object = array();
$object["content"] = array();
$object["users"] = array();
$mysqli = connect_db();
// Autocomplete users and products.
$query = 'SELECT user FROM users';
if ($result = $mysqli->query($query)) {
while ($users = $result->fetch_assoc()) {
$object["users"][] = $users["user"];
}
$result->close();
}
else {
$this->Log('Roster->Show 1: '.$mysqli->error);
}
// strtotime depends on the timezone.
$this->config->set_timezone();
// Get user details to show in grid.
$detail = new Module($this->user, $this->owner, "detail", $this->config);
$all_users = $detail->Factory("AllUsers");
$query = 'SELECT user, timestamp FROM roster WHERE timestamp > '.
strtotime("-21 days").' ORDER BY timestamp DESC';
if ($result = $mysqli->query($query)) {
while ($roster = $result->fetch_assoc()) {
$user = $roster["user"];
$name = $user;
$phone = "";
if (is_array($all_users[$user])) {
if ($all_users[$user]["first"] !== "") {
$name = $all_users[$user]["first"];
}
if ($all_users[$user]["last"] !== "") {
$name .= " ".$all_users[$user]["last"];
}
$phone = $all_users[$user]["phone"];
}
$object["content"][] = array("date" => $roster["timestamp"] * 1000,
"username" => $user,
"fullname" => $name,
"phone" => $phone);
}
$result->close();
}
else {
$this->Log('Roster->Show 2: '.$mysqli->error);
}
$mysqli->close();
return $object;
}
}
?>
\ No newline at end of file
...@@ -182,7 +182,7 @@ class Stock extends Base { ...@@ -182,7 +182,7 @@ class Stock extends Base {
public function Install($path) { public function Install($path) {
// Append dobrado.stock.js to the existing dobrado.js file. // Append dobrado.stock.js to the existing dobrado.js file.
// Note that updating the module is only available when logged in. // Note that the module is only available when logged in.
$this->AppendScript($path, "dobrado.stock.js", false); $this->AppendScript($path, "dobrado.stock.js", false);
$mysqli = connect_db(); $mysqli = connect_db();
$query = 'CREATE TABLE IF NOT EXISTS stock ('. $query = 'CREATE TABLE IF NOT EXISTS stock ('.
...@@ -319,10 +319,12 @@ class Stock extends Base { ...@@ -319,10 +319,12 @@ class Stock extends Base {
'ORDER BY name'; 'ORDER BY name';
if ($result = $mysqli->query($query)) { if ($result = $mysqli->query($query)) {
while ($stock = $result->fetch_assoc()) { while ($stock = $result->fetch_assoc()) {
$price = (float)$stock["price"];
$price = number_format($price, 2, ".", "");
$object[] = array("name" => $stock["name"], $object[] = array("name" => $stock["name"],
"user" => $stock["user"], "user" => $stock["user"],
"unit" => $stock["unit"], "unit" => $stock["unit"],
"price" => (float)$stock["price"], "price" => $price,
"category" => $stock["category"], "category" => $stock["category"],
"available" => (int)$stock["available"]); "available" => (int)$stock["available"]);
} }
......
...@@ -909,7 +909,13 @@ $special.draginit = $special.dragstart = $special.dragend = drag; ...@@ -909,7 +909,13 @@ $special.draginit = $special.dragstart = $special.dragend = drag;
var d = new Date(value); var d = new Date(value);
var year = d.getFullYear(); var year = d.getFullYear();
var month = d.getMonth() + 1; var month = d.getMonth() + 1;
if (month < 10) {
month = "0" + month;
}
var day = d.getDate(); var day = d.getDate();
if (day < 10) {
day = "0" + day;
}
return year + "-" + month + "-" + day; return year + "-" + month + "-" + day;
} }
})(jQuery); })(jQuery);
......
...@@ -67,8 +67,9 @@ if (!this.dobrado.payment) { ...@@ -67,8 +67,9 @@ if (!this.dobrado.payment) {
forceFitColumns: true, forceFitColumns: true,
}; };
grid = dobrado.grid.instance(id, payments, columns, options); grid = dobrado.grid.instance(id, payments, columns, options);
grid.setSelectionModel(new Slick.RowSelectionModel());
grid.onClick.subscribe(function(e, item) { grid.onClick.subscribe(function(e, item) {
showPayment(payments[item.row]); showPayment(payments[item.row]);
}); });
} }
loadBankDetails(); loadBankDetails();
......
...@@ -60,6 +60,7 @@ if (!this.dobrado.purchase) { ...@@ -60,6 +60,7 @@ if (!this.dobrado.purchase) {
// Create a grid instance with empty rows, which will be populated // Create a grid instance with empty rows, which will be populated
// when a user is selected to assign purchases to. // when a user is selected to assign purchases to.
grid = dobrado.grid.instance(id, [], columns, options); grid = dobrado.grid.instance(id, [], columns, options);
grid.setSelectionModel(new Slick.RowSelectionModel());
grid.onClick.subscribe(function(e, item) { grid.onClick.subscribe(function(e, item) {
showPurchase(item.row); showPurchase(item.row);
}); });
...@@ -214,14 +215,15 @@ if (!this.dobrado.purchase) { ...@@ -214,14 +215,15 @@ if (!this.dobrado.purchase) {
// Display a warning or reminder if this user owes money. // Display a warning or reminder if this user owes money.
if (user in purchase.outstanding) { if (user in purchase.outstanding) {
if (purchase.outstanding[user] >= purchase.info) { if (purchase.outstanding[user] >= purchase.info) {
var outstanding = purchase.outstanding[user].toFixed(2);
if (purchase.outstanding[user] >= purchase.warning) { if (purchase.outstanding[user] >= purchase.warning) {
$(".warning-level .user").html(user); $(".warning-level .user").html(user);
$(".warning-level .outstanding").html(purchase.outstanding[user]); $(".warning-level .outstanding").html(outstanding);
$(".warning-level").show(); $(".warning-level").show();
} }
else { else {
$(".info-level .user").html(user); $(".info-level .user").html(user);
$(".info-level .outstanding").html(purchase.outstanding[user]); $(".info-level .outstanding").html(outstanding);
$(".info-level").show(); $(".info-level").show();
} }
} }
......
if (!this.dobrado.roster) {
dobrado.roster = {};
}
(function() {
'use strict';
// This is a representation of the roster in json.
var roster = [];
// This is an instance of slick grid, if available on the page.
var grid = null;
$(function() {
// Don't run if the module isn't on the page.
if ($(".roster").length === 0) return;
$("#roster-form .remove").button().click(remove);
$("#roster-form .submit").button().click(submit);
$("#roster-date-input").val("").datepicker({ dateFormat: "yy-mm-dd" });
dobrado.log("Loading roster...", "info");
$.post("/php/request.php", { request: "roster",
action: "list",
token: dobrado.token },
function(response) {
if (dobrado.checkResponseError(response, "roster list")) {
return;
}
roster = JSON.parse(response);
updateNames();
// If a grid module is on the page load the roster.
if ($(".grid").length !== 0) {
var id = "#" + $(".grid").attr("id");
var columns =
[{ id : "date", name: "Date", field: "date", width: 100,
formatter: Slick.Formatters.Timestamp },
{ id : "fullname", name: "Name", field: "fullname", width: 200 },
{ id : "phone", name: "Phone", field: "phone", width: 100 }];
var options = {
enableColumnReorder: false,
forceFitColumns: true,
};
grid = dobrado.grid.instance(id, roster.content, columns, options);
grid.setSelectionModel(new Slick.RowSelectionModel());
grid.onClick.subscribe(function(e, item) {
showUser(roster.content[item.row]);
});
}
});
});
function showUser(user) {
$("#roster-name-input").val(user.username);
$("#roster-date-input").val(dobrado.formatDate(user.date));
}
function updateNames() {
// Create an autocomplete list of usernames.
var usernames = [];
$.each(roster.users, function(index, item) {
usernames.push(item);
});
$("#roster-name-input").autocomplete({ source: usernames });
}
function remove() {
dobrado.log("Removing user...", "info");
update("remove");
return false;
}
function submit() {
dobrado.log("Saving user...", "info");
update("submit");
return false;
}
function update(action) {
// Convert the date input into a timestamp.
var val = $("#roster-date-input").val();
var timestamp = new Date(val).getTime();
$.post("/php/request.php",
{ request: "roster",
action: action,
name: $("#roster-name-input").val(),
timestamp: timestamp,
token: dobrado.token },
function(response) {
if (dobrado.checkResponseError(response, "roster remove")) {
return;
}
// When an item is added or removed a new roster is returned.
roster = JSON.parse(response);
updateNames();
// Update the grid if available, which also references roster.
if (grid) {
grid.setData(roster.content);
grid.updateRowCount();
grid.render();
}
// Reset fields in the form.
$("#roster-name-input").val("");
$("#roster-date-input").val("");
});
}
})();
...@@ -45,8 +45,9 @@ if (!this.dobrado.stock) { ...@@ -45,8 +45,9 @@ if (!this.dobrado.stock) {
forceFitColumns: true, forceFitColumns: true,
}; };
grid = dobrado.grid.instance(id, stock, columns, options); grid = dobrado.grid.instance(id, stock, columns, options);
grid.setSelectionModel(new Slick.RowSelectionModel());
grid.onClick.subscribe(function(e, item) { grid.onClick.subscribe(function(e, item) {
showProduct(stock[item.row]); showProduct(stock[item.row]);
}); });
} }
}); });
......
...@@ -567,7 +567,13 @@ if (!this.dobrado) { ...@@ -567,7 +567,13 @@ if (!this.dobrado) {
var d = new Date(value); var d = new Date(value);
var year = d.getFullYear(); var year = d.getFullYear();
var month = d.getMonth() + 1; var month = d.getMonth() + 1;
if (month < 10) {
month = "0" + month;
}
var day = d.getDate(); var day = d.getDate();
if (day < 10) {
day = "0" + day;
}
return year + "-" + month + "-" + day; return year + "-" + month + "-" + day;
}; };
......
...@@ -324,6 +324,7 @@ if (!this.dobrado.account) { ...@@ -324,6 +324,7 @@ if (!this.dobrado.account) {
logout(); logout();
} }
else if (option === "preferences" || option === "register") { else if (option === "preferences" || option === "register") {
dobrado.log("Loading " + option + " dialog...", "info");
dobrado.closeEditor({}); dobrado.closeEditor({});
$.post("/php/request.php", { request: "account", $.post("/php/request.php", { request: "account",
action: option, action: option,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment