Compare commits

...
18 Commits
Author SHA1 Message Date
pvincent bc939a5bdb tagged as 1.11.4 2022-08-22 10:48:54 +04:00
pvincent 4a052ea707 no more config.xml first time 2022-08-22 10:48:41 +04:00
pvincent f139fcfefb Update 'README.md' 2021-12-03 20:18:54 +04:00
pvincent 347a81dc66 Update 'README.md' 2021-08-31 21:34:26 +04:00
pvincent d142fc1eac Update 'README.md' 2021-08-31 21:22:59 +04:00
pvincent e039ed4fe5 better readme 2021-08-31 20:04:52 +04:00
pvincent 44d2248ba5 screenshot 2021-08-31 19:54:35 +04:00
pvincent 34e7527442 screenshot 2021-08-31 19:15:28 +04:00
pvincent ecffe9bb4e tagged as 1.11.3 2021-08-30 23:22:46 +04:00
pvincent 6e7382633f css footer margin 0 2021-08-30 23:22:19 +04:00
pvincent bb50c92230 tagged as 1.11.2 2021-08-30 22:49:49 +04:00
pvincent 98dffaebed fix config missing key 2021-08-30 22:49:34 +04:00
pvincent ca6aceffbc tagged as 1.11.1 2021-08-30 21:48:13 +04:00
pvincent c4ea83cca9 better README 2021-08-30 21:47:25 +04:00
pvincent 6c4aa6d9ea tagged as 1.11.0 2021-08-30 21:10:58 +04:00
pvincent cdfe52715f simpler config + new logo 2021-08-30 21:10:33 +04:00
pvincent 8bd119a818 maintain 2021-08-30 18:30:00 +04:00
pvincent 0854d556fe cagettepéi 2021-08-30 17:44:14 +04:00
21 changed files with 1251 additions and 1444 deletions
+1 -1
View File
@@ -1 +1 @@
1.10.2
1.11.4
+3 -3
View File
@@ -7,9 +7,9 @@ ENV?="dev"
install:
#copy config file from template first time only
@if [ ! -f config.xml ]; then \
cp config.xml.dist config.xml; \
fi
# @if [ ! -f config.xml ]; then \
# cp config.xml.dist config.xml; \
# fi
@if [ $(ENV) = "dev" ]; then \
make install_dev; \
+60 -44
View File
@@ -1,67 +1,80 @@
CAGETTE PEI
===========
Fourche du logiciel [Cagette.net](https://github.com/CagetteNet) à partir de la version 0.9.2 Novembre 2018
Cagette Péi est un logiciel libre qui favorise les circuits courts.
Il a été adapté pour les besoins des AMAPs sur le marché réunionnais.
Certaines portions du code source de Cagette.net n'étant plus disponibles en téléchargement,
j'ai repris sur la base d'un existant pour adapter au marché local réunionnais et leurs AMAPéi.
> <french>
> Fourche du logiciel [Cagette.net](https://github.com/CagetteNet) à partir de la version 0.9.2 Novembre 2018. Certaines portions de code n'étant plus disponibles en téléchargement à partir de cette date, le logiciel a été repris, adapté puis réactualisé. Pour plus d'information, contact@artcode.re
> </french>
## INSTALL FROM SCRATCH (debian-buster)
![Screenshot](www/img/screenshot.png)
* apt install -y curl
* curl -L https://deb.nodesource.com/setup_8.x | bash -
* apt install -y nodejs=8.17.0-1nodesource1
* apt install -y sudo haxe apache2 make git imagemagick gettext libapache2-mod-neko mariadb-server
* mysql -u root <<EOF
## PREREQUISITE MARIADB
```bash
apt install -y mariadb-server
mysql -u root <<EOF
CREATE DATABASE cagettepei;
GRANT ALL ON cagettepei.* TO 'cagettepei'@'%' IDENTIFIED BY 'cagettepei';
EOF
* cd /var/www
* git clone https://git.artcode.re/cagetters/cagettepei.git
* cd cagettepei
* make install ENV=dev # first time
* make compile # classes
* make templates # templates + i18n
* vim /etc/apache2/sites-available/cagettepei.conf
```
## INSTALL FROM SCRATCH
Rk: Works on any Debian (>=Buster) compatible server!
```
apt install -y curl
curl -L https://deb.nodesource.com/setup_8.x | bash -
apt install -y nodejs=8.17.0-1nodesource1
apt install -y sudo haxe apache2 make git imagemagick gettext libapache2-mod-neko mariadb-server sendemail libio-socket-ssl-perl libnet-ssleay-perl
cd /var/www
git clone https://git.artcode.re/cagetters/cagettepei.git
cd cagettepei
make install ENV=dev
vim /etc/apache2/sites-available/cagettepei.conf
```
```
<VirtualHost *:80>
ServerName cagettepei
DocumentRoot /var/www/cagettepei/www
DirectoryIndex index.n
DocumentRoot /var/www/cagettepei/www/
CustomLog ${APACHE_LOG_DIR}/cagettepei/access.log combined
</VirtualHost>
```
* sed -i '/<Directory \/var\/www\/>/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' /etc/apache2/apache2.conf
* a2dissite 000-default.conf
* a2ensite cagettepei.conf
* a2enmod neko rewrite
* systemctl restart apache2
```bash
sed -i '/<Directory \/var\/www\/>/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' /etc/apache2/apache2.conf
a2dissite 000-default.conf
a2ensite cagettepei.conf
a2enmod rewrite
mkdir -p /var/log/apache2/cagettepei
systemctl restart apache2
```
## CONFIGURATION
* cd /var/www/cagettepei
* vim config.xml
```bash
cd /var/www/cagettepei
vim config.xml
```
```
<config
host = "<DOMAIN.TLD>"
database = "mysql://cagettepei:cagettepei@localhost/cagettepei"
key = "<SECRET_PHRASE>"
name = "CagettePéi"
default_email = "<EMAIL>"
webmaster_email = "<EMAIL>"
database="mysql://cagettepei:cagettepei@localhost/cagettepei"
smtp_host="localhost"
smtp_port="25"
smtp_user=""
smtp_pass=""
lang="fr"
langs="fr"
langnames="Français"
maintain="0"
debug = "0"
sqllog = "0"
maintain = "0"
cache = "1"
cachetpl = "0"
/>
@@ -72,16 +85,19 @@ ADMIN RESET PASSWORD
go to http://localhost for ERROR + table regeneration, then
* cd /var/www/cagettepei
* SECRET=$(grep key= config.xml | cut -d= -f2 | cut -d'"' -f2)
* echo "insert into User values (1,'fr',MD5('${SECRET}cagettepei'),1,'Administrateur','Cagette Péi', 'admin', null, null, null, null, null, null, null, null, null, now(), now(),6,null, null)" | mysql -h localhost -u cagettepei -pcagettepei cagettepei
```
cd /var/www/cagettepei
SECRET=$(grep key config.xml | cut -d= -f2 | cut -d'"' -f2)
echo "insert into User values (1,'fr',MD5('${SECRET}cagettepei'),1,'Administrateur','Cagette Péi', 'admin', null, null, null, null, null, null, null, null, null, now(), now(),6,null, null)" | mysql -h localhost -u cagettepei -pcagettepei cagettepei
```
then, connect with admin / cagettepei
### change admin password
* echo "update User set pass=MD5('${SECRET}cagettepei') where id=1" | mysql -h localhost -u cagettepei -pcagettepei cagettepei
```
echo "update User set pass=MD5('${SECRET}cagettepei') where id=1" | mysql -h localhost -u cagettepei -pcagettepei cagettepei
```
SYSTEMD-TIMERS
--------------
@@ -98,7 +114,7 @@ SYSTEMD-TIMERS
SELECTOR=$1
for i in /var/www/cagettepei-* ; do
for i in /var/www/cagettepei* ; do
if [[ -d $i ]]; then
cd $i/www
echo "cron-$SELECTOR in: $i"
+3 -8
View File
@@ -1,19 +1,14 @@
<config
database = "mysql://<USER>:<PASSWORD>@<HOST>/<DBNAME>"
host = "<URL without http>"
name = "<HTML head title>"
default_email = "<EMAIL>"
webmaster_email = "<EMAIL>"
key = "<SECRET_PHRASE>"
maintain="0"
cache="1"
cachetpl="0"
debug="0"
sqllog="0"
maintain="0"
lang="fr"
langs="fr"
langnames="Français"
cache="1"
cachetpl="0"
/>
+1 -1
View File
@@ -1,7 +1,7 @@
::use 'admin/design.mtt'::
<h3>Console d'administration de Cagette.net</h3>
<h3>Console d'administration de CagettePéi</h3>
<p>
::hDate(now)::
</p>
+9 -100
View File
@@ -13,11 +13,7 @@
::if groupName!=null && noGroup!=true::
<h1>::groupName::</h1>
::else::
<div style="margin-bottom:22px;" >
<a href="https://git.artcode.re/cagetters/cagettepei" target="_blank">
<img src="/img/logo3.png" alt="::NAME::" />
</a>
</div>
<h1>::_("Cagette.net")::</h1>
::end::
</div>
@@ -129,10 +125,13 @@
<div class="row" id="footer">
<div class="col-md-9" >
<a href="https://git.artcode.re/cagetters/cagette" target="_blank">
<img src="/img/logo.png" alt="::_("Cagette.net")::"/>
</a>
<div class="col-md-2" >
<img width="120" style="border: white 5px solid;" src="/img/logo-mini.jpg" alt="::_("Cagette.net")::" title="Logo ::_("Cagette.net")::"/>
</div>
<div class="col-md-7" style="padding-top:1em">
Cagette Péi est un logiciel libre qui favorise les circuits courts.<br/>
Il a été adapté pour les besoins des AMAPs sur le marché réunionnais.<br/>
</div>
<div class="col-md-3" >
@@ -149,57 +148,12 @@
</li>
</ul>
<!--<p style="position: absolute;display: block;top: 96px;width: 700px;">
<b>::raw _("Vous êtes producteur ?")::</b>
::raw _("Découvrez nos formations gratuites pour utiliser <b>Cagette Pro</b> ")::
&nbsp;&nbsp;<a href="http://alilo.fr/formations-producteurs" target="_blank" class="btn btn-xs btn-info">C'est parti !</a>
</p>-->
</div>
<!--
<div class="col-md-3" >
::_("FOLLOW US")::
<ul class="cagsocialmedia">
<li class="cagfb">
<a title="Facebook" href="https://www.facebook.com/cagette" target="_blank"> <i class="fa fa-facebook"></i></a>
</li>
<li class="cagtwitter">
<a title="Twitter" href="https://twitter.com/Cagettenet" target="_blank"> <i class="fa fa-twitter"></i></a>
</li>
<li class="cagyoutube">
<a title="Youtube" href="https://www.youtube.com/channel/UC3cvGxAUrbN9oSZmr1oZEaw" target="_blank"> <i class="fa fa-youtube"></i></a>
</li>
<li style="background-color:#333;">
<a title="Github" href="https://github.com/bablukid/cagette" target="_blank"> <i class="fa fa-github"></i></a>
</li>
</ul>
</div>
-->
<!--
<div class="col-md-3">
::_("CONTACT US")::
<ul>
<li>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
<input type="hidden" name="cmd" value="_s-xclick"/>
<input type="hidden" name="hosted_button_id" value="S9KT7FQS7P622"/>
<input type="image" src="https://www.paypalobjects.com/fr_FR/FR/i/btn/btn_donate_LG.gif" border="0" name="submit" alt="PayPal, le réflexe sécurité pour payer en ligne"/>
<img alt="" border="0" src="https://www.paypalobjects.com/fr_FR/i/scr/pixel.gif" width="1" height="1"/>
</form>
</li>
</ul>
</div>
-->
</div>
<div class="row" id="subfooter">
<!--
::raw _("Cagette.net is made by <a href='https://www.alilo.fr' target='_blank'><img src='/img/alilo-trans-black.png' /></a>")::<br/>
-->
<span>version cagettepei-<a href="https://git.artcode.re/cagetters/cagettepei/src/tag/::VERSION::">::VERSION::</a></span>
<span>version cagettepei-<a target="_blank" href="https://git.artcode.re/cagetters/cagettepei/src/tag/::VERSION::">::VERSION::</a></span>
</div>
<div class="row">
@@ -219,49 +173,4 @@
</div>
</div>
::if (false && user!=null && user.isAmapManager())::
<script>
// Include the UserVoice JavaScript SDK (only needed once on a page)
UserVoice=window.UserVoice||[];(function(){var uv=document.createElement('script');uv.type='text/javascript';uv.async=true;uv.src='//widget.uservoice.com/sayZ1eIZLfSZUa3IwslHCw.js';var s=document.getElementsByTagName('script')[0];s.parentNode.insertBefore(uv,s)})();
//
// UserVoice Javascript SDK developer documentation:
// https://www.uservoice.com/o/javascript-sdk
//
// Set colors
UserVoice.push(['set', {
accent_color: '#6aba2e',
trigger_color: 'white',
trigger_background_color: '#e2753a'
}]);
// Identify the user and pass traits
// To enable, replace sample data with actual user traits and uncomment the line
UserVoice.push(['identify', {
//email: 'john.doe@example.com', // Users email address
//name: 'John Doe', // Users real name
//created_at: 1364406966, // Unix timestamp for the date the user signed up
//id: 123, // Optional: Unique id of the user (if set, this should not change)
//type: 'Owner', // Optional: segment your users by type
//account: {
// id: 123, // Optional: associate multiple users with a single account
// name: 'Acme, Co.', // Account name
// created_at: 1364406966, // Unix timestamp for the date the account was created
// monthly_rate: 9.99, // Decimal; monthly rate of the account
// ltv: 1495.00, // Decimal; lifetime value of the account
// plan: 'Enhanced' // Plan name for the account
//}
}]);
// Add default trigger to the bottom-right corner of the window:
UserVoice.push(['addTrigger', { mode: 'smartvote', trigger_position: 'bottom-right' }]);
// Or, use your own custom trigger:
//UserVoice.push(['addTrigger', '#id', { mode: 'smartvote' }]);
// Autoprompt for Satisfaction and SmartVote (only displayed under certain conditions)
UserVoice.push(['autoprompt', {}]);
</script>
::end::
::end::
+2 -2
View File
@@ -1,4 +1,4 @@
::use 'design.mtt'::
<!--::use 'design.mtt'::-->
<div class="text-center" style="height:400px;width:100%;">
<h1>
<span class="glyphicon glyphicon-cog"></span>
@@ -14,4 +14,4 @@
</div>
::end::
<!--::end::-->
+1 -1
View File
@@ -47,5 +47,5 @@
"bugs": {
"url": "https://github.com/bablukid/cagette/issues"
},
"version": "1.10.2"
"version": "1.11.3"
}
-8
View File
@@ -1,5 +1,4 @@
import db.User;
import thx.semver.Version;
import Common;
class App extends sugoi.BaseApp {
@@ -10,13 +9,6 @@ class App extends sugoi.BaseApp {
public var eventDispatcher:hxevents.Dispatcher<Event>;
public var plugins:Array<sugoi.plugin.IPlugIn>;
/**
* Version management
* @doc https://github.com/fponticelli/thx.semver
*/
// public static var VERSION = ([0,9,2] : Version).withPre("july");
// public static var VERSION = ([0,9,2] : Version).withPre(MyMacros.getGitShortSHA(), MyMacros.getGitCommitDate());
// public static var VERSION = "cagette-péi " + MyMacros.getGitCommitDate();
public static var VERSION = "cagette-pei"; // empty yet, cf.BaseApp.loadConfig
public function new() {
+158 -166
View File
@@ -1,4 +1,5 @@
package controller;
import db.UserContract;
import sugoi.form.elements.DateDropdowns;
import sugoi.form.elements.Input;
@@ -7,14 +8,13 @@ import sugoi.form.Form;
import db.Contract;
import Common;
import plugin.Tutorial;
using Std;
import service.OrderService;
class Contract extends Controller
{
public function new()
{
class Contract extends Controller {
public function new() {
super();
}
@@ -29,14 +29,12 @@ class Contract extends Controller
*/
@tpl("contract/default.mtt")
function doDefault() {
// Create the list of links to change the language
var langs = App.config.get("langs").split(";");
var langNames = App.config.get("langnames").split(";");
var langs = App.config.get("langs", "fr").split(";");
var langNames = App.config.get("langnames", "Français").split(";");
var i = 0;
var langLinks = "";
for (lang in langs)
{
for (lang in langs) {
langLinks += "<li><a href=\"?lang=" + langs[i] + "\">" + langNames[i] + "</a></li>";
i++;
}
@@ -51,7 +49,8 @@ class Contract extends Controller
}
var ua = db.UserAmap.get(app.user, app.user.amap);
if (ua == null) throw Error("/", t._("You are not a member of this group"));
if (ua == null)
throw Error("/", t._("You are not a member of this group"));
var constOrders = null;
var varOrders = new Map<String, Array<db.UserContract>>();
@@ -64,7 +63,8 @@ class Contract extends Controller
constOrders = [];
for (c in contracts) {
var orders = app.user.getOrdersFromContracts([c]);
if (orders.length == 0) continue;
if (orders.length == 0)
continue;
constOrders.push({contract: c, orders: service.OrderService.prepare(orders)});
}
@@ -91,7 +91,6 @@ class Contract extends Controller
// final structure
var varOrders2 = new Array<{date:Date, orders:Array<UserOrder>}>();
for (k in varOrders.keys()) {
var d = new Date(k.split("-")[0].parseInt(), k.split("-")[1].parseInt() - 1, k.split("-")[2].parseInt(), 0, 0, 0);
var orders = service.OrderService.prepare(Lambda.list(varOrders[k]));
@@ -106,14 +105,10 @@ class Contract extends Controller
view.varOrders = varOrders2;
view.constOrders = constOrders;
// tutorials
if (app.user.isAmapManager()) {
// actions
if (app.params.exists('startTuto')) {
// start a tuto
app.user.lock();
var t = app.params.get('startTuto');
@@ -121,7 +116,6 @@ class Contract extends Controller
app.user.update();
}
// tuto state
var tutos = new Array<{name:String, completion:Float, key:String}>();
@@ -129,7 +123,8 @@ class Contract extends Controller
var t = Tutorial.all().get(k);
var completion = null;
if (app.user.tutoState!=null && app.user.tutoState.name == k) completion = app.user.tutoState.step / t.steps.length;
if (app.user.tutoState != null && app.user.tutoState.name == k)
completion = app.user.tutoState.step / t.steps.length;
tutos.push({name: t.name, completion: completion, key: k});
}
@@ -155,9 +150,9 @@ class Contract extends Controller
*/
@tpl("form.mtt")
function doEdit(c:db.Contract) {
view.category = 'contractadmin';
if (!app.user.isContractManager(c)) throw Error('/', t._("Forbidden action"));
if (!app.user.isContractManager(c))
throw Error('/', t._("Forbidden action"));
view.title = t._("Edit contract ::contractName::", {contractName: c.name});
@@ -176,7 +171,8 @@ class Contract extends Controller
c.amap = group;
// checks & warnings
if (c.hasPercentageOnOrders() && c.percentageValue==null) throw Error("/contract/edit/"+c.id, t._("If you would like to add fees to the order, define a rate (%) and a label."));
if (c.hasPercentageOnOrders() && c.percentageValue == null)
throw Error("/contract/edit/" + c.id, t._("If you would like to add fees to the order, define a rate (%) and a label."));
if (c.hasStockManagement()) {
for (p in c.getProducts()) {
@@ -193,7 +189,6 @@ class Contract extends Controller
app.session.addMessage(t._("Managing stock is not available for CSA contracts"), true);
}
c.update();
// update rights
@@ -212,7 +207,6 @@ class Contract extends Controller
x.update();
}
}
}
throw Ok("/contractAdmin/view/" + c.id, t._("Contract updated"));
@@ -224,7 +218,6 @@ class Contract extends Controller
@tpl("contract/insertChoose.mtt")
function doInsertChoose() {
// checkToken();
}
/**
@@ -232,8 +225,10 @@ class Contract extends Controller
*/
@tpl("form.mtt")
function doInsert(?type:Int) {
if (!app.user.canManageAllContracts()) throw Error('/', t._("Forbidden action"));
if (type == null) throw Redirect('/contract/insertChoose');
if (!app.user.canManageAllContracts())
throw Error('/', t._("Forbidden action"));
if (type == null)
throw Redirect('/contract/insertChoose');
view.title = if (type == db.Contract.TYPE_CONSTORDERS) t._("Create a contract with fixed orders") else t._("Create a contract with variable orders");
@@ -271,8 +266,8 @@ class Contract extends Controller
* Delete a contract (... and its products, orders & distributions)
*/
function doDelete(c:db.Contract) {
if (!app.user.canManageAllContracts()) throw Error("/contractAdmin", t._("You don't have the authorization to remove a contract"));
if (!app.user.canManageAllContracts())
throw Error("/contractAdmin", t._("You don't have the authorization to remove a contract"));
if (checkToken()) {
c.lock();
@@ -282,7 +277,8 @@ class Contract extends Controller
var orders = db.UserContract.manager.search($productId in Lambda.map(products, function(p) return p.id));
var qt = 0.0;
for ( o in orders) qt += o.quantity; //there could be "zero c qt" orders
for (o in orders)
qt += o.quantity; // there could be "zero c qt" orders
if (qt > 0) {
throw Error("/contractAdmin", t._("You cannot delete this contract because some orders are linked to it."));
}
@@ -315,12 +311,13 @@ class Contract extends Controller
*/
@tpl("contract/order.mtt")
function doOrder(c:db.Contract) {
// checks
if (app.user.amap.hasPayments()) throw Redirect("/contract/orderAndPay/" + c.id);
if (app.user.amap.hasShopMode()) throw Redirect("/shop");
if (!c.isUserOrderAvailable()) throw Error("/", t._("This contract is not opened for orders"));
if (app.user.amap.hasPayments())
throw Redirect("/contract/orderAndPay/" + c.id);
if (app.user.amap.hasShopMode())
throw Redirect("/shop");
if (!c.isUserOrderAvailable())
throw Error("/", t._("This contract is not opened for orders"));
var distributions = [];
// If its a varying contract, we display a column by distribution
@@ -335,7 +332,6 @@ class Contract extends Controller
var products = c.getProducts();
if (c.type == db.Contract.TYPE_VARORDER) {
for (d in distributions) {
var datas = [];
for (p in products) {
@@ -343,33 +339,30 @@ class Contract extends Controller
var order = db.UserContract.manager.select($user == app.user && $productId == p.id && $distributionId == d.id, true);
if (order != null) ua.order = order;
if (order != null)
ua.order = order;
datas.push(ua);
}
userOrders.push({distrib: d, datas: datas});
}
} else {
var datas = [];
for (p in products) {
var ua = {order: null, product: p};
var order = db.UserContract.manager.select($user == app.user && $productId == p.id, true);
if (order != null) ua.order = order;
if (order != null)
ua.order = order;
datas.push(ua);
}
userOrders.push({distrib: null, datas: datas});
}
// form check
if (checkToken()) {
// get dsitrib if needed
// var distrib : db.Distribution = null;
// if (c.type == db.Contract.TYPE_VARORDER) {
@@ -377,117 +370,11 @@ class Contract extends Controller
// }
for (k in app.params.keys()) {
if (k.substr(0, 1) != "d") continue;
var qt = app.params.get(k);
if (qt == "") continue;
var pid = null;
var did = null;
try{
pid = Std.parseInt(k.split("-")[1].substr(1));
did = Std.parseInt(k.split("-")[0].substr(1));
}catch (e:Dynamic){trace("unable to parse key "+k); }
//find related element in userOrders
var uo = null;
for ( x in userOrders){
if (x.distrib!=null && x.distrib.id != did) {
if (k.substr(0, 1) != "d")
continue;
}else{
for (a in x.datas){
if (a.product.id == pid){
uo = a;
break;
}
}
}
}
if (uo == null) throw t._("Could not find the product ::produ:: and delivery ::deliv::", {produ:pid, deliv:did});
var q = 0.0;
if (uo.product.hasFloatQt ) {
var param = StringTools.replace(qt, ",", ".");
q = Std.parseFloat(param);
}else {
q = Std.parseInt(qt);
}
if (uo.order != null) {
OrderService.edit(uo.order, q);
}else {
OrderService.make(app.user, q, uo.product, did);
}
}
throw Ok("/contract/order/"+c.id, t._("Your order has been updated"));
}
view.c = view.contract = c;
view.userOrders = userOrders;
}
/**
* Make an order by contract ( standard mode ) + payment process
*/
@tpl("contract/orderAndPay.mtt")
function doOrderAndPay(c:db.Contract ) {
//checks
if (!app.user.amap.hasPayments()) throw Redirect("/contract/order/" + c.id);
if (app.user.amap.hasShopMode()) throw Redirect("/");
if (!c.isUserOrderAvailable()) throw Error("/", t._("This contract is not opened for orders"));
var distributions = [];
/* If its a varying contract, we display a column by distribution*/
if (c.type == db.Contract.TYPE_VARORDER) {
distributions = db.Distribution.getOpenToOrdersDeliveries(c);
}
//list of distribs with a list of product and optionnaly an order
var userOrders = new Array< {distrib:db.Distribution,datas:Array<{order:db.UserContract,product:db.Product}>} >();
var products = c.getProducts();
for ( d in distributions){
var datas = [];
for ( p in products) {
var ua = { order:null, product:p };
var order : db.UserContract = null;
if (c.type == db.Contract.TYPE_VARORDER) {
order = db.UserContract.manager.select($user == app.user && $productId == p.id && $distributionId==d.id, true);
}else {
order = db.UserContract.manager.select($user == app.user && $productId == p.id, true);
}
if (order != null) ua.order = order;
datas.push(ua);
}
userOrders.push({distrib:d,datas:datas});
}
//form check
if (checkToken()) {
//get distrib if needed
var distrib = null;
if (c.type == db.Contract.TYPE_VARORDER) {
distrib = db.Distribution.manager.get(Std.parseInt(app.params.get("distribution")), false);
}
var orders : OrderInSession = {products:[],userId:app.user.id,total:0};
for (k in app.params.keys()) {
if (k.substr(0, 1) != "d") continue;
var qt = app.params.get(k);
if (qt == "") continue;
if (qt == "")
continue;
var pid = null;
var did = null;
@@ -513,7 +400,117 @@ class Contract extends Controller
}
}
if (uo == null) throw t._("Could not find the product ::produ:: and delivery ::deliv::", {produ:pid, deliv:did});
if (uo == null)
throw t._("Could not find the product ::produ:: and delivery ::deliv::", {produ: pid, deliv: did});
var q = 0.0;
if (uo.product.hasFloatQt) {
var param = StringTools.replace(qt, ",", ".");
q = Std.parseFloat(param);
} else {
q = Std.parseInt(qt);
}
if (uo.order != null) {
OrderService.edit(uo.order, q);
} else {
OrderService.make(app.user, q, uo.product, did);
}
}
throw Ok("/contract/order/" + c.id, t._("Your order has been updated"));
}
view.c = view.contract = c;
view.userOrders = userOrders;
}
/**
* Make an order by contract ( standard mode ) + payment process
*/
@tpl("contract/orderAndPay.mtt")
function doOrderAndPay(c:db.Contract) {
// checks
if (!app.user.amap.hasPayments())
throw Redirect("/contract/order/" + c.id);
if (app.user.amap.hasShopMode())
throw Redirect("/");
if (!c.isUserOrderAvailable())
throw Error("/", t._("This contract is not opened for orders"));
var distributions = [];
/* If its a varying contract, we display a column by distribution*/
if (c.type == db.Contract.TYPE_VARORDER) {
distributions = db.Distribution.getOpenToOrdersDeliveries(c);
}
// list of distribs with a list of product and optionnaly an order
var userOrders = new Array<{distrib:db.Distribution, datas:Array<{order:db.UserContract, product:db.Product}>}>();
var products = c.getProducts();
for (d in distributions) {
var datas = [];
for (p in products) {
var ua = {order: null, product: p};
var order:db.UserContract = null;
if (c.type == db.Contract.TYPE_VARORDER) {
order = db.UserContract.manager.select($user == app.user && $productId == p.id && $distributionId == d.id, true);
} else {
order = db.UserContract.manager.select($user == app.user && $productId == p.id, true);
}
if (order != null)
ua.order = order;
datas.push(ua);
}
userOrders.push({distrib: d, datas: datas});
}
// form check
if (checkToken()) {
// get distrib if needed
var distrib = null;
if (c.type == db.Contract.TYPE_VARORDER) {
distrib = db.Distribution.manager.get(Std.parseInt(app.params.get("distribution")), false);
}
var orders:OrderInSession = {products: [], userId: app.user.id, total: 0};
for (k in app.params.keys()) {
if (k.substr(0, 1) != "d")
continue;
var qt = app.params.get(k);
if (qt == "")
continue;
var pid = null;
var did = null;
try {
pid = Std.parseInt(k.split("-")[1].substr(1));
did = Std.parseInt(k.split("-")[0].substr(1));
} catch (e:Dynamic) {
trace("unable to parse key " + k);
}
// find related element in userOrders
var uo = null;
for (x in userOrders) {
if (x.distrib != null && x.distrib.id != did) {
continue;
} else {
for (a in x.datas) {
if (a.product.id == pid) {
uo = a;
break;
}
}
}
}
if (uo == null)
throw t._("Could not find the product ::produ:: and delivery ::deliv::", {produ: pid, deliv: did});
// quantity
var q = 0.0;
@@ -528,7 +525,6 @@ class Contract extends Controller
var p = db.Product.manager.get(pid, false);
orders.total += p.getPrice() * q;
}
App.current.session.data.order = orders;
@@ -539,22 +535,17 @@ class Contract extends Controller
} else {
throw Ok("/transaction/pay/", t._("In order to save your order, please choose a means of payment."));
}
}
view.c = view.contract = c;
view.userOrders = userOrders;
}
/**
* A user edit an order for a multidistrib.
*/
@tpl("contract/orderByDate.mtt")
function doEditOrderByDate(date:Date) {
if (app.user.amap.hasPayments()) {
// when payments are active, the user cannot modify his order
throw Redirect("/");
@@ -562,9 +553,9 @@ class Contract extends Controller
// cannot edit order if date is in the past
if (Date.now().getTime() > date.getTime()) {
var msg = t._("This delivery has already taken place, you can no longer modify the order.");
if (app.user.isContractManager()) msg += t._("<br/>As the manager of the contract you can modify the order from this page: <a href='/contractAdmin'>Management of contracts</a>");
if (app.user.isContractManager())
msg += t._("<br/>As the manager of the contract you can modify the order from this page: <a href='/contractAdmin'>Management of contracts</a>");
throw Error("/contract", msg);
}
@@ -575,23 +566,23 @@ class Contract extends Controller
var cids = Lambda.map(app.user.amap.getActiveContracts(true), function(c) return c.id);
var distribs = db.Distribution.manager.search(($contractId in cids) && $date >= d1 && $date <= d2, false);
var orders = db.UserContract.manager.search($userId==app.user.id && $distributionId in Lambda.map(distribs,function(d)return d.id) );
var orders = db.UserContract.manager.search($userId == app.user.id
&& $distributionId in Lambda.map(distribs, function(d) return d.id));
view.orders = service.OrderService.prepare(orders);
view.date = date;
// form check
if (checkToken()) {
var orders_out = [];
for (k in app.params.keys()) {
var param = app.params.get(k);
if (k.substr(0, "product".length) == "product") {
// trouve le produit dans userOrders
var pid = Std.parseInt(k.substr("product".length));
var order = Lambda.find(orders, function(uo) return uo.product.id == pid);
if (order == null) throw t._("Error, could not find the order");
if (order == null)
throw t._("Error, could not find the order");
var q = 0.0;
if (order.product.hasFloatQt) {
@@ -606,7 +597,8 @@ class Contract extends Controller
if (order.distribution.canOrderNow()) {
// met a jour la commande
var o = OrderService.edit(order, quantity);
if(o!=null) orders_out.push( o );
if (o != null)
orders_out.push(o);
}
}
}
-2
View File
@@ -19,8 +19,6 @@ class ContractAdmin extends Controller {
if (!app.user.isContractManager())
throw Error("/", t._("You don't have the authorization to manage contracts"));
view.nav = ["contractadmin"];
App.log("first message");
}
public function sendNav(c) {
+7 -5
View File
@@ -31,8 +31,8 @@ class Messages extends Controller {
var lists = getLists();
form.addElement(new StringInput("senderName", t._("Sender name"), senderName, true));
form.addElement(new StringInput("senderMail", t._("Sender E-Mail"), senderMail, true));
form.addElement(new StringSelect("list", t._("Recipients"), lists, "1", true, null, "style='width:500px;'"));
form.addElement(new StringInput("subject", t._("Subject:"), "", false, null, "style='width:500px;'"));
form.addElement(new StringSelect("list", t._("Recipients"), lists, "3", true, null, "style='width:500px;'"));
form.addElement(new StringInput("subject", t._("Subject:"), "", true, null, "style='width:500px;'"));
form.addElement(new TextArea("text", t._("Message:"), "", false, null, "style='width:500px;height:350px;'"));
if (form.checkToken()) {
@@ -52,7 +52,7 @@ class Messages extends Controller {
// send mail confirmation link
var e = new sugoi.mail.Mail();
e.setSender(App.config.get("default_email"), t._("Cagette.net"));
e.setSubject(subject);
e.setSubject('[cagettepei] $subject');
var replyTo = form.getValueOf("senderMail");
var replyToName = form.getValueOf("senderName");
@@ -63,9 +63,13 @@ class Messages extends Controller {
e.addRecipient(x);
var text:String = form.getValueOf("text");
if (text == null)
text = "";
var html = app.processTemplate("mail/message.mtt", {text: text, group: app.user.amap, list: getListName(listId)});
e.setHtmlBody(html);
App.log('text=[$text]');
App.log('html= ${e.getHtmlBody()}');
App.sendMail(e, app.user.getAmap(), listId, app.user);
// store message
@@ -82,8 +86,6 @@ class Messages extends Controller {
lm.insert();
throw Ok("/messages", t._("The message has been sent"));
} else {
App.log('Administrator #${app.user.id} <${senderName}> prepares sending an email from choices list');
}
view.form = form;
+23 -38
View File
@@ -1,4 +1,5 @@
package controller;
import haxe.crypto.Md5;
import sugoi.form.elements.Input;
import sugoi.form.Form;
@@ -7,22 +8,16 @@ import sugoi.form.elements.StringInput;
import sugoi.form.validators.EmailValidator;
import ufront.mail.*;
class User extends Controller
{
public function new()
{
class User extends Controller {
public function new() {
super();
}
@tpl("user/default.mtt")
function doDefault() {
}
function doDefault() {}
@tpl("user/login.mtt")
function doLogin() {
if (App.current.user != null) {
throw Redirect('/');
}
@@ -35,15 +30,14 @@ class User extends Controller
}
}
/**
* Choose which group to connect to.
*/
@logged
@tpl("user/choose.mtt")
function doChoose(?args:{amap:db.Amap}) {
if (app.user == null) throw t._("You are not connected");
if (app.user == null)
throw t._("You are not connected");
var amaps = db.UserAmap.manager.search($user == app.user, false);
@@ -68,7 +62,6 @@ class User extends Controller
view.amaps = amaps;
view.wl = db.WaitingList.manager.search($user == app.user, false);
#if plugins
view.pros = pro.db.PUserCompany.getCompanies(app.user);
#end
@@ -85,7 +78,6 @@ class User extends Controller
*/
@tpl("user/forgottenPassword.mtt")
function doForgottenPassword(?key:String, ?u:db.User) {
// STEP 1
var step = 1;
var error:String = null;
@@ -118,10 +110,12 @@ class User extends Controller
var email:String = askmailform.getValueOf("email");
var user = db.User.manager.select(email == $email, false);
// could be user 2
if(user==null) user = db.User.manager.select(email == $email2, false);
if (user == null)
user = db.User.manager.select(email == $email2, false);
// user not found
if (user == null) throw Error(url, t._("This E-mail is not linked to a known account"));
if (user == null)
throw Error(url, t._("This E-mail is not linked to a known account"));
// create token
var token = haxe.crypto.Md5.encode("chp" + Std.random(1000000000));
@@ -130,8 +124,9 @@ class User extends Controller
var m = new sugoi.mail.Mail();
m.setSender(App.config.get("default_email"), t._("Cagette.net"));
m.setRecipient(email, user.name);
m.setSubject( "["+App.config.NAME+"] : "+t._("Password change"));
m.setHtmlBody( app.processTemplate('mail/forgottenPassword.mtt', { user:user, link:'http://' + App.config.HOST + '/user/forgottenPassword/'+token+"/"+user.id }) );
m.setSubject("[" + App.config.NAME + "] " + t._("Password change"));
m.setHtmlBody(app.processTemplate('mail/forgottenPassword.mtt',
{user: user, link: 'http://' + App.config.HOST + '/user/forgottenPassword/' + token + "/" + user.id}));
App.sendMail(m);
}
@@ -151,7 +146,6 @@ class User extends Controller
step = 4;
if (chpassform.getValueOf("pass1") == chpassform.getValueOf("pass2")) {
var uid = Std.parseInt(chpassform.getValueOf("uid"));
var user = db.User.manager.get(uid, true);
var pass = chpassform.getValueOf("pass1");
@@ -161,10 +155,12 @@ class User extends Controller
var m = new sugoi.mail.Mail();
m.setSender(App.config.get("default_email"), t._("Cagette.net"));
m.setRecipient(user.email, user.name);
if(user.email2!=null) m.setRecipient(user.email2, user.name);
if (user.email2 != null)
m.setRecipient(user.email2, user.name);
m.setSubject("[" + App.config.NAME + "] : " + t._("New password confirmed"));
var emails = [user.email];
if(user.email2!=null) emails.push(user.email2);
if (user.email2 != null)
emails.push(user.email2);
var params = {
user: user,
emails: emails.join(", "),
@@ -173,7 +169,6 @@ class User extends Controller
}
m.setHtmlBody(app.processTemplate('mail/newPasswordConfirmed.mtt', params));
App.sendMail(m);
} else {
error = t._("You must key-in two times the same password");
}
@@ -187,7 +182,6 @@ class User extends Controller
view.error = error;
}
/**
* generate a custom key for transactionnal emails, valid during the current day
*/
@@ -195,12 +189,11 @@ class User extends Controller
// return haxe.crypto.Md5.encode(App.config.get("key")+m.email+(Date.now().getDate())).substr(0,12);
// }
@logged
@tpl("form.mtt")
function doDefinePassword(?key:String, ?u:db.User) {
if (app.user.isFullyRegistred()) throw Error("/", t._("You already have a password"));
if (app.user.isFullyRegistred())
throw Error("/", t._("You already have a password"));
var form = new Form("definepass");
var pass1 = new StringInput("pass1", t._("Your new password"));
@@ -211,14 +204,11 @@ class User extends Controller
form.addElement(pass2);
if (form.isValid()) {
if (form.getValueOf("pass1") == form.getValueOf("pass2")) {
app.user.lock();
app.user.setPass(form.getValueOf("pass1"));
app.user.update();
throw Ok('/', t._("Congratulations, your account is now protected by a password."));
} else {
form.addError(t._("You must key-in two times the same password"));
}
@@ -232,24 +222,19 @@ class User extends Controller
* @param k
*/
public function doValidate(k:String) {
var uid = Std.parseInt(sugoi.db.Cache.get("validation" + k));
if (uid == null || uid==0) throw Error('/user/login', t._("Your invitation is invalid or expired ($k)"));
if (uid == null || uid == 0)
throw Error('/user/login', t._("Your invitation is invalid or expired ($k)"));
var user = db.User.manager.get(uid, true);
db.User.login(user, user.email);
var groups = user.getAmaps();
if(groups.length>0) app.session.data.amapId = groups.first().id;
if (groups.length > 0)
app.session.data.amapId = groups.first().id;
sugoi.db.Cache.destroy("validation" + k);
throw Ok("/user/definePassword", t._("Congratulations ::userName::, your account is validated!", {userName: user.getName()}));
}
}
+20 -51
View File
@@ -1,9 +1,9 @@
package controller.admin;
import haxe.web.Dispatch;
import Common;
class Admin extends Controller {
public function new() {
super();
view.category = 'admin';
@@ -13,7 +13,6 @@ class Admin extends Controller {
var e = Nav(nav, "admin");
app.event(e);
view.nav = e.getParameters()[0];
}
@tpl("admin/default.mtt")
@@ -30,24 +29,18 @@ class Admin extends Controller {
var count = sugoi.db.BufferedMail.manager.count($sdate == null);
view.browser = new sugoi.tools.ResultsBrowser(count, 10, browse);
view.num = count;
}
@tpl("form.mtt")
function doSmtp() {
var f = new sugoi.form.Form("emails");
var data = [
{label:"SMTP",value:"smtp"},
{label:"Mandrill API",value:"mandrill"},
];
var data = [{label: "SMTP", value: "smtp"}, {label: "Mandrill API", value: "mandrill"},];
var mailer = sugoi.db.Variable.get("mailer") == null ? "smtp" : sugoi.db.Variable.get("mailer");
var host = sugoi.db.Variable.get("smtp_host")==null ? App.config.get("smtp_host") : sugoi.db.Variable.get("smtp_host");
var port = sugoi.db.Variable.get("smtp_port")==null ? App.config.get("smtp_port") : sugoi.db.Variable.get("smtp_port");
var user = sugoi.db.Variable.get("smtp_user")==null ? App.config.get("smtp_user") : sugoi.db.Variable.get("smtp_user");
var pass = sugoi.db.Variable.get("smtp_pass")==null ? App.config.get("smtp_pass") : sugoi.db.Variable.get("smtp_pass");
var host = sugoi.db.Variable.get("smtp_host") == null ? "<SMTP_SERVER>" : sugoi.db.Variable.get("smtp_host");
var port = sugoi.db.Variable.get("smtp_port") == null ? "587" : sugoi.db.Variable.get("smtp_port");
var user = sugoi.db.Variable.get("smtp_user") == null ? "" : sugoi.db.Variable.get("smtp_user");
var pass = sugoi.db.Variable.get("smtp_pass") == null ? "" : sugoi.db.Variable.get("smtp_pass");
f.addElement(new sugoi.form.elements.StringSelect("mailer", "Mailer", data, mailer));
f.addElement(new sugoi.form.elements.StringInput("smtp_host", "host", host));
@@ -55,13 +48,11 @@ class Admin extends Controller {
f.addElement(new sugoi.form.elements.StringInput("smtp_user", "user", user));
f.addElement(new sugoi.form.elements.StringInput("smtp_pass", "pass", pass));
if (f.isValid()) {
for (k in ["mailer", "smtp_host", "smtp_port", "smtp_user", "smtp_pass"]) {
sugoi.db.Variable.set(k, f.getValueOf(k));
}
throw Ok("/admin/emails", t._("Configuration updated"));
}
view.title = t._("Email service configuration");
@@ -72,12 +63,9 @@ class Admin extends Controller {
d.dispatch(new controller.admin.Plugins());
}
@tpl("admin/taxo.mtt")
function doTaxo() {
view.categ = db.TxpCategory.manager.all();
}
/**
@@ -91,31 +79,31 @@ class Admin extends Controller {
view.like = args.like != null ? args.like : "";
var sql = "";
if( args.user!=null ) sql += " AND uid="+args.user;
if (args.user != null)
sql += " AND uid=" + args.user;
// if( args.like!=null && args.like != "" ) sql += " AND error like "+sys.db.Manager.cnx.quote("%"+args.like+"%");
if (args.empty) {
sys.db.Manager.cnx.request("truncate table Error");
}
var errorsStats = sys.db.Manager.cnx.request("select count(id) as c, DATE_FORMAT(date,'%y-%m-%d') as day from Error where date > NOW()- INTERVAL 1 MONTH "+sql+" group by day order by day").results();
var errorsStats = sys.db.Manager.cnx.request("select count(id) as c, DATE_FORMAT(date,'%y-%m-%d') as day from Error where date > NOW()- INTERVAL 1 MONTH "
+ sql
+ " group by day order by day")
.results();
view.errorsStats = errorsStats;
view.browser = new sugoi.tools.ResultsBrowser(
sugoi.db.Error.manager.unsafeCount("SELECT count(*) FROM Error WHERE 1 "+sql),
20,
function(start, limit) { return sugoi.db.Error.manager.unsafeObjects("SELECT * FROM Error WHERE 1 "+sql+" ORDER BY date DESC LIMIT "+start+","+limit,false); }
);
view.browser = new sugoi.tools.ResultsBrowser(sugoi.db.Error.manager.unsafeCount("SELECT count(*) FROM Error WHERE 1 " + sql), 20,
function(start, limit) {
return sugoi.db.Error.manager.unsafeObjects("SELECT * FROM Error WHERE 1 " + sql + " ORDER BY date DESC LIMIT " + start + "," + limit, false);
});
}
@tpl("admin/graph.mtt")
function doGraph(?key:String, ?year:Int, ?month:Int) {
var from = new Date(year, month, 1, 0, 0, 0);
var to = new Date(year, month + 1, 0, 23, 59, 59);
if (app.params.exists("recompute")) {
switch (key) {
case "basket":
for (d in 1...to.getDate()) {
@@ -124,12 +112,8 @@ class Admin extends Controller {
var value = db.Basket.manager.count($cdate >= _from && $cdate <= _to);
var g = db.Graph.record(key, value, _from);
// trace(value,_from,g);
}
}
}
var data = db.Graph.getRange(key, from, to);
@@ -140,18 +124,14 @@ class Admin extends Controller {
var averageValue = 0.0;
var total = 0.0;
for( d in data) total += d.value;
for (d in data)
total += d.value;
averageValue = total / data.length;
view.total = total;
view.averageValue = averageValue;
}
function doFixDistribValidation() {
Sys.println("===== Liste des distributions ayant été re-validées ====<br>");
// Get the current group
@@ -161,18 +141,14 @@ class Admin extends Controller {
// Get all the validated distributions for this given group
var validatedDistribs = db.Distribution.manager.search(($contractId in contractIds) && $validated == true, {orderBy: date}, false);
for (distrib in validatedDistribs) {
service.PaymentService.validateDistribution(distrib);
Sys.println(distrib.toString() + "<br>");
}
Sys.println("===== Fin de la liste ====");
}
function doCheckDistribValidation() {
Sys.println("===== Liste des distributions validées ayant des opérations/paiements non validés ====<br>");
// Get the current group
@@ -182,11 +158,10 @@ class Admin extends Controller {
// Get all the validated distributions for this given group
var validatedDistribs = db.Distribution.manager.search(($contractId in contractIds) && $validated == true, {orderBy: date}, false);
for (distrib in validatedDistribs) {
for (user in distrib.getUsers()) {
var basket = db.Basket.get(user, distrib.place, distrib.date);
if (basket == null || basket.isValidated()) continue;
if (basket == null || basket.isValidated())
continue;
for (order in basket.getOrders()) {
if (!order.paid) {
@@ -197,27 +172,21 @@ class Admin extends Controller {
var operation = basket.getOrderOperation(false);
if (operation != null) {
if (operation.pending) {
Sys.println(distrib.toString() + "<br>");
Sys.println(operation.toString() + "<br>");
}
for (payment in basket.getPayments()) {
if (payment.pending) {
Sys.println(distrib.toString() + "<br>");
Sys.println(payment.toString() + "<br>");
}
}
}
}
}
Sys.println("===== Fin de la liste ====");
}
}
-1
View File
@@ -45,7 +45,6 @@ class BaseApp {
var PATH = Web.getCwd() + "../";
var json = haxe.Json.parse(sys.io.File.getContent(PATH + "package.json"));
App.VERSION = json.version;
App.log('configuration has been reloaded, VERSION=${App.VERSION}');
}
+6 -7
View File
@@ -3,7 +3,6 @@ package sugoi;
import sugoi.Web;
class Config {
public var PATH:String;
// public var json : Dynamic;
public var xml:Xml;
@@ -20,16 +19,16 @@ class Config {
public function new(?path:String) {
PATH = (path != null) ? path : Web.getCwd() + "../";
//json = haxe.Json.parse(sys.io.File.getContent(PATH + "config.json"));
xml = Xml.parse(sys.io.File.getContent(PATH + "config.xml")).firstElement();
LANG = get("lang");
LANGS = get("langs").split(";");
NAME = get("name", "cagettepei");
LANG = get("lang", "fr");
LANGS = get("langs", "fr").split(";");
TPL = PATH + "lang/" + LANG + "/tpl/";
TPL_TMP = PATH + "lang/" + LANG + "/tmp/";
DEBUG = get("debug", "0") == "1";
HOST = get("host");
NAME = get("name");
KEY = get("key");
DATA_HOST = get("dataHost", "data." + HOST);
SQL_LOG = getBool("sqllog", false);
@@ -42,7 +41,8 @@ class Config {
public function getBool(val:String, ?def) {
var v = get(val);
if( v == null ) return def;
if (v == null)
return def;
return (v == "1" || v == "true");
}
@@ -59,5 +59,4 @@ class Config {
public function getInt(val:String, ?def:Int):Int {
return Std.parseInt(get(val, Std.string(def)));
}
}
+89 -138
View File
@@ -1,4 +1,3 @@
/**
Cagette.net SASS stylesheet
@@ -6,15 +5,18 @@
**/
@import url('https://fonts.googleapis.com/css?family=Cabin:400,400i,700');
@import url("https://fonts.googleapis.com/css?family=Cabin:400,400i,700");
//@import '_shop';
@import '_map';
@import "_map";
/*body{
background-color:#F8F4E5 !important;
}*/
h1,h2,h3,h4{
h1,
h2,
h3,
h4 {
margin-top: 4px !important;
margin-bottom: 8px !important;
font-style: italic;
@@ -66,9 +68,11 @@ ul.nav li {
/* Footer */
#footer {
background: #84BD55;
background: #84bd55;
border-radius: 8px;
padding: 20px;
margin: 0;
ul > li > a {
color: #333;
}
@@ -98,21 +102,19 @@ ul.nav li {
.cagsocialmedia li {
display: inline-block;
text-align: center;
}
.cagfb {
background-color : #4267B2;
background-color: #4267b2;
}
.cagtwitter {
background-color : #1DA1F2;
background-color: #1da1f2;
}
.cagyoutube {
background-color : #FF0000;
background-color: #ff0000;
}
}
#subfooter {
@@ -130,12 +132,14 @@ ul.nav li {
.sqlLog {
margin-top: 24px;
font-size: 10px;
background:#AAA;
a{ color:#666; }
background: #aaa;
a {
color: #666;
}
}
.contact {
border:2px solid #CCC ;
border: 2px solid #ccc;
border-radius: 8px;
margin: 8px;
padding: 8px;
@@ -145,13 +149,12 @@ ul.nav li {
.homeBlock {
margin-bottom: 32px;
background:#FFF;
background: #fff;
border-radius: 8px;
position: relative;
padding: 8px;
.content {
margin: 8px 8px 8px 90px;
}
}
@@ -164,16 +167,15 @@ span.panel-title{
.article {
margin-bottom: 16px;
background:#FFF;
background: #fff;
border-radius: 8px;
position: relative;
padding: 8px;
}
.white {
margin-bottom: 16px;
background:#FFF;
background: #fff;
border-radius: 4px;
position: relative;
}
@@ -185,7 +187,7 @@ span.panel-title{
/* block marron */
.block {
margin-bottom: 12px;
background : #FFF;
background: #fff;
border-radius: 8px;
position: relative;
padding: 8px;
@@ -194,11 +196,11 @@ span.panel-title{
/* block marron + contours */
.block2 {
margin-bottom: 32px;
background : #F0D277;
background: #f0d277;
border-radius: 8px;
position: relative;
padding: 8px;
border: 2px solid #C3A04C;
border: 2px solid #c3a04c;
}
/* product in shop */
@@ -224,13 +226,12 @@ table.product{
}
}
/* GLOBAL TABLE SKINNING */
//separator between rows
table.table tr.head > td {
//border-top: 1px solid #BBB;
border-top: 3px solid #DDD;
border-top: 3px solid #ddd;
height: 30px;
font-size: 120%;
vertical-align: bottom;
@@ -238,7 +239,7 @@ table.table tr.head>td{
//sub-row, darker bg
table.table tr.subrow {
background-color:#EEE;
background-color: #eee;
}
//listing have no overflow
@@ -247,22 +248,20 @@ table.listing tr td{
overflow-x: hidden;
}
table.table tr.disabled td,table.table tr.inactive td{
table.table tr.disabled td,
table.table tr.inactive td {
opacity: 0.4;
}
/* DIV TABLE */
// used in UserOrder react comp
div.tableHeader {
font-weight: bold;
color: #AAA;
border-bottom: 1px solid #DDD;
color: #aaa;
border-bottom: 1px solid #ddd;
margin-bottom: 12px;
}
/*table.table>tbody>tr>th{
background-color:white;
color:#BBB;
@@ -270,31 +269,22 @@ div.tableHeader{
}*/
div.reportHeader {
background-color:#DDD;
background-color: #ddd;
}
/* a product order in a table style */
.productOrder {
border-bottom:1px solid #DDD;
border-bottom: 1px solid #ddd;
margin-bottom: 6px;
.infos {
color:#AAA;
color: #aaa;
font-size: 0.8em;
}
}
/* A product reference */
.ref {
color:#AAA;
color: #aaa;
font-family: monospace;
font-size: 0.9em;
}
@@ -303,7 +293,7 @@ div.reportHeader{
.linkToShare {
font-family: Monospace;
padding: 12px;
border: 1px solid #DDD;
border: 1px solid #ddd;
border-radius: 6px;
background-color: #f5f5f5;
}
@@ -311,7 +301,7 @@ div.reportHeader{
/* make <a> like clickable divs */
.clickable {
display: block;
border:1px solid #CCC;
border: 1px solid #ccc;
border-radius: 8px;
color: inherit;
background-color: white;
@@ -320,16 +310,16 @@ div.reportHeader{
&:hover {
cursor: pointer;
background-color:lighten(#F0D277,10%);
border-color:darken(#F0D277,10%);
background-color: lighten(#f0d277, 10%);
border-color: darken(#f0d277, 10%);
text-decoration: none;
transition: all 0.15s ease;
}
&:active {
cursor: pointer;
background-color:#F0D277;
border-color:darken(#F0D277,10%);
background-color: #f0d277;
border-color: darken(#f0d277, 10%);
text-decoration: none;
transform: scale(0.95);
}
@@ -338,7 +328,6 @@ div.reportHeader{
background-color: lightgray;
cursor: not-allowed;
}
}
/* a cagette group block (use it with .clickable ) */
@@ -387,18 +376,15 @@ div.reportHeader{
a {
color: #777;
}
}
}
/*
SHOP v1
*/
.shop {
.header {
background-color:#749E3C;
background-color: #749e3c;
display: inline-block;
width: 100%;
@@ -410,10 +396,13 @@ div.reportHeader{
line-height: 22px;
color: white;
a{ color:white; }
.info{ font-weight: bold; }
a {
color: white;
}
.info {
font-weight: bold;
}
}
.body {
background: white;
@@ -425,14 +414,12 @@ div.reportHeader{
font-weight: bold;
font-size: 1.2em;
color: #583816;
border-bottom:1px solid #CCC;
border-bottom: 1px solid #ccc;
width: 100%;
}
}
.product {
display: inline-block;
.name {
@@ -444,12 +431,9 @@ div.reportHeader{
color: #900;
font-weight: bold;
}
}
}
.price {
font-weight: bold;
font-size: 1.3em;
@@ -463,13 +447,11 @@ div.reportHeader{
.detail {
color: #999999;
font-size: 90%;
}
//in shop page
#cartContainer.scrolled {
position: fixed;
top: 125px;
}
@@ -492,10 +474,8 @@ div.reportHeader{
}
#cart {
margin-bottom: 12px;
div.order {
margin-bottom: 8px;
@@ -508,12 +488,10 @@ div.reportHeader{
//font-weight:bold;
margin-bottom: 12px;
margin-top: 12px;
border-top:1px solid #FFF;
}
border-top: 1px solid #fff;
}
}
}
.place {
color: #666;
@@ -521,11 +499,11 @@ div.reportHeader{
margin-top: 13px;
padding: 8px;
font-size: 13px;
border-top:1px solid #CCC ;
border-top: 1px solid #ccc;
}
.distribMessage {
color:#FFF;
color: #fff;
font-weight: bold;
padding: 4px;
margin-top: 13px;
@@ -535,7 +513,6 @@ div.reportHeader{
/*border-top:1px solid #333 ;*/
}
.dateBoxOffset {
position: absolute;
top: -16px;
@@ -543,10 +520,9 @@ div.reportHeader{
display: block;
}
.dateBox {
border-radius: 8px;
background-color: #c59654;
color:#FFF;
color: #fff;
font-size: 13px;
line-height: 13px;
@@ -560,7 +536,7 @@ div.reportHeader{
.box {
line-height: 22px;
background-color:#FFFFFF;
background-color: #ffffff;
color: #666;
font-size: 14px;
font-weight: bold;
@@ -571,15 +547,13 @@ div.reportHeader{
/* place link */
a {
color: #FFFFFF !important;
color: #ffffff !important;
}
a:hover {
color: #FFFFFF !important;
color: #ffffff !important;
}
}
/* categories */
span.tag {
color: white;
@@ -596,45 +570,42 @@ span.tag.active{
line-height: 45px;
}
/**
Popovers for help and tutorials
**/
.popover {
color: white;
font-size: 14px;
//font-family:'Arial','sans-serif' !important;
h3.popover-title {
padding: 4px;
color:#BB9931 !important;
border-bottom:1px solid #BB9931 !important;
color: #bb9931 !important;
border-bottom: 1px solid #bb9931 !important;
background-color: none;
}
.popover-content {
font-size: 16px;
b{ color:#FC0; font-weight:normal; }
b {
color: #fc0;
font-weight: normal;
}
}
.footer {
border-top: 1px solid #BB9931;
border-top: 1px solid #bb9931;
height: 45px;
padding: 12px 0;
.pull-left .btn {
background-color: #583816;
color: white;
border: 1px solid white;
}
.pull-right .btn {
background-color:#FC0;
background-color: #fc0;
color: #583816;
border: 1px solid #583816;
}
@@ -643,11 +614,10 @@ span.tag.active{
/* skin a modal like a tuto popover */
.modal.help {
.modal-header {
font-size: 1.3em;
color:#BB9931 !important;
border-bottom:1px solid #BB9931 !important;
color: #bb9931 !important;
border-bottom: 1px solid #bb9931 !important;
font-weight: bold !important;
//font-family:'Arial','sans-serif' !important;
background-color: #583816 !important;
@@ -656,13 +626,11 @@ span.tag.active{
.modal-content {
background-color: #583816 !important;
color: white;
}
.modal-footer {
border-top:1px solid #BB9931 !important;
border-top: 1px solid #bb9931 !important;
}
}
/* hightlight a zone for tutos */
.highlight {
@@ -670,23 +638,19 @@ span.tag.active{
border-radius: 16px;
}
/* Distribution box for the homepage */
.distrib {
margin: 0px 0px 28px 0px;
position: relative;
.header {
display: block;
height: 72px;
overflow: hidden;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
color:#FFF;
background-color:#749E3C;
color: #fff;
background-color: #749e3c;
vertical-align: middle;
margin: 0;
padding: 6px 6px 6px 90px;
@@ -696,7 +660,7 @@ span.tag.active{
opacity: 1;
}
&.orders {
background-color:#B2823F;
background-color: #b2823f;
}
.info {
@@ -704,24 +668,26 @@ span.tag.active{
line-height: 22px;
/* place link */
a {
color: #FFFFFF !important;
&:hover{ color: #FFFFFF !important; }
color: #ffffff !important;
&:hover {
color: #ffffff !important;
}
}
}
.date {
line-height: 23px;
background-color:#FFFFFF;
background-color: #ffffff;
color: #666;
font-size: 14px;
text-align: center;
margin: 0 8px 0 0;
border-radius: 6px;
border: 4px solid #C6C6C6;
border: 4px solid #c6c6c6;
}
.address, .closing{
.address,
.closing {
font-weight: normal;
font-size: 0.9em;
line-height: 16px;
@@ -737,30 +703,28 @@ span.tag.active{
.content {
padding: 6px 6px 6px 6px;
background-color:#85B14D;
background-color: #85b14d;
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
&.disabled {
background:#AAA;
background: #aaa;
opacity: 1;
}
&.orders {
background:#FFF;
background: #fff;
padding-left: 50px;
}
.footer {
color: #999;
a{color:#999;}
a {
color: #999;
}
font-size: 0.9em;
}
}
}
div.groupImg {
@@ -788,7 +752,6 @@ div.product{
margin-right: 12px;
vertical-align: middle;
}
}
//Product in ProductSelect React component
@@ -811,14 +774,10 @@ div.productSelect{
div.product {
display: inline-block;
}
}
// Cagette Pro Catalogs
div.productBox {
div.productImg {
background-size: cover;
height: 220px;
@@ -842,7 +801,6 @@ div.productBox{
}
}
// typeahead ( autocomplete js lib )
.tt-menu {
background-color: #f5e3ac;
@@ -851,7 +809,7 @@ div.productBox{
.tt-suggestion {
background-color: #f5e3ac;
padding: 8px;
border-top:1px solid #CCC;
border-top: 1px solid #ccc;
color: darken(#f5e3ac, 60%);
cursor: pointer;
font-style: italic;
@@ -862,9 +820,8 @@ div.productBox{
//txp product input
#pInput {
.txpProduct {
color:#AAA;
color: #aaa;
font-weight: bold;
font-size: 0.8em;
margin: 4px 0;
@@ -876,7 +833,6 @@ div.productBox{
}
}
//Product composer
/*
div.ProductComp{
@@ -894,15 +850,13 @@ div.ProductComp{
//basket
div.basketNumber {
display: inline-block;
background-color: #333;
border-radius: 10px;
padding: 6px;
font-weight: bold;
color:#CCC;
color: #ccc;
}
tr.success td div.basketNumber {
@@ -924,13 +878,10 @@ tr.danger td div.basketNumber{
width: 100%;
margin: 0;
padding: 8px;
border-top: 3px solid #CCC;
border-top: 3px solid #ccc;
z-index: 99;
}
/*!
* https://github.com/YouCanBookMe/react-datetime
*/
@@ -945,7 +896,7 @@ tr.danger td div.basketNumber{
margin-top: 1px;
z-index: 99999 !important;
background: #fff;
box-shadow: 0 1px 3px rgba(0,0,0,.1);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
border: 1px solid #f9f9f9;
}
.rdtOpen .rdtPicker {
@@ -988,7 +939,7 @@ tr.danger td div.basketNumber{
position: relative;
}
.rdtPicker td.rdtToday:before {
content: '';
content: "";
display: inline-block;
border-left: 7px solid transparent;
border-bottom: 7px solid #428bca;
Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

+1 -1
View File
@@ -2237,7 +2237,7 @@ msgid ""
"Welcome in the group of ::name::!\n"
" You can look at the delivery planning or make a new order."
msgstr ""
"Bienvenue sur la cagette de ::name:: !\n"
"Bienvenue sur le CagettePéi de ::name:: !\n"
" Vous pouvez consulter votre planning de distribution ou faire une nouvelle "
"commande."