Commit 1488a819 by Jose Antonio

Merged branch develop into develop

parents f373d407 e2ef3827
......@@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
classpath 'com.android.tools.build:gradle:2.3.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
......
......@@ -145,7 +145,14 @@ public class RestapiWrapper {
if (Character.isAlphabetic(response.charAt(0)))
response.append('\'').insert(0,'\'');
Log.i(LOG_TAG, "Raw server answer: " + response);
for (int i=0;i<(int)(((float)response.length())/3000)+1;i++) {
int begin= i * 3000;
int end = (i+1) * 3000;
if (end>response.length()) end=response.length();
Log.d(LOG_TAG, "Raw server answer(" + i+ "): " + response.substring(begin, end));
}
try {
JSONresponse = new JSONObject("{ "+SERVER_RESULT+": " + response + (responseCode == HttpURLConnection.HTTP_OK
? "}"
......@@ -154,7 +161,7 @@ public class RestapiWrapper {
JSONresponse = null;
Log.e(RestapiWrapper.class.getCanonicalName(),e.getMessage());
}
Log.i(LOG_TAG, "server answer: " + JSONresponse.toString());
Log.i(LOG_TAG, "Server answer: " + JSONresponse.toString());
return JSONresponse;
}
......
......@@ -78,6 +78,7 @@ public class Vocabulary implements Iterable<Picto> {
modifyAttsPicto(picto_cat, picto_id, args.getJSONObject("attributes"));
} catch (JSONException e) {
e.printStackTrace();
Log.e(LOG_TAG,e.getMessage());
}
break;
}
......@@ -92,7 +93,9 @@ public class Vocabulary implements Iterable<Picto> {
JSONObject attrs_picto = args.getJSONObject("attributes");
attrs_picto.put(Picto.JSON_ATTTRS.STUPICTO_ID,args.getInt("id"));
Picto newPicto=new Picto(picto_id, uri, attrs_picto);
Picto prev_picto=find_picto(newPicto.get_category(), newPicto.get_row(),newPicto.get_column());
Picto prev_picto=PCBcontext.getPcbdb().getCurrentUser().has_categories()
? find_picto(newPicto.get_category(), newPicto.get_row(),newPicto.get_column())
: find_picto(newPicto.getFreeRow(),newPicto.getFreeColumn());
if (prev_picto!=null) {
Log.i(LOG_TAG, "Pictogram "+prev_picto.get_translation()+":"+prev_picto.get_id()+" to be replaced by "+newPicto.get_translation()+":"+newPicto.get_id());
......@@ -129,20 +132,24 @@ public class Vocabulary implements Iterable<Picto> {
* The only issue is: what happens whether the upload fails? --> The image will be lost.
* TODO: keep record of failed uploaded images to re-include as local pictos
*/
private void synchronize_upload() {
private boolean synchronize_upload() {
boolean upload_pending=false;
try {
PCBcontext.getPcbdb().getStudentVocabulary(this);
if (this.pictos.isEmpty())
PCBcontext.getPcbdb().getStudentVocabulary(this);
} catch (JSONException e) {
Log.e(this.getClass().getName(), " Picto json error from local storage: " + e.getMessage());
}
for (Picto picto: this) {
if (picto.local_status()) {
upload_pending=true;
new PictoUploader(picto).uploadState();
Log.i(this.getClass().getCanonicalName(), "Picto status modified while offline. Picto translation: '" +
picto.get_translation() + "', id:" + picto.get_id() + " Local status?" + picto.local_status());
}
if (picto.is_local())
try {
upload_pending=true;
Log.i(this.getClass().getCanonicalName(), "Picto added while offline. Picto translation: '" +
picto.get_translation() + "', id:" + picto.get_id() + " Local status?" + picto.local_status());
new PictoUploader(picto).upload();
......@@ -152,6 +159,7 @@ public class Vocabulary implements Iterable<Picto> {
}
}
return upload_pending;
}
/**
* the vocabulary is (i) updated to and (ii) downloaded from the server.
......@@ -159,65 +167,67 @@ public class Vocabulary implements Iterable<Picto> {
public void synchronize() {
synchronize_upload(); // (i) uploading
boolean upload_pending=synchronize_upload(); // (i) uploading
// and (ii) downloading
final String picto_str="/pictos";
String operation=PCBcontext.getPcbdb().getCurrentUser().get_restapi_operation_stu()+picto_str;
PCBcontext.getRestapiWrapper().ask(operation, new RestapiWrapper.iRestapiListener() {
@Override
public void preExecute() {
if (!upload_pending) {
final String picto_str = "/pictos";
String operation = PCBcontext.getPcbdb().getCurrentUser().get_restapi_operation_stu() + picto_str;
PCBcontext.getRestapiWrapper().ask(operation, new RestapiWrapper.iRestapiListener() {
@Override
public void preExecute() {
}
}
@Override
public void result(JSONArray result) {
if (result != null) {
final String jpicto = "picto";
final String jid = "id";
final String juri = "uri";
final String jattributes = "attributes";
Picto[] pictos = new Picto[result.length()];
JSONObject picto, attributes ;
JSONObject stupicto=null;
try {
for (int i=0; i < result.length(); i++) {
stupicto=result.getJSONObject(i);
picto = stupicto.getJSONObject(jpicto);
attributes = stupicto.getJSONObject(jattributes);
attributes.put(Picto.JSON_ATTTRS.STUPICTO_ID,stupicto.get(jid));
pictos[i] = new Picto(picto.getInt(jid),
@Override
public void result(JSONArray result) {
if (result != null) {
final String jpicto = "picto";
final String jid = "id";
final String juri = "uri";
final String jattributes = "attributes";
Picto[] pictos = new Picto[result.length()];
JSONObject picto, attributes;
JSONObject stupicto = null;
try {
for (int i = 0; i < result.length(); i++) {
stupicto = result.getJSONObject(i);
picto = stupicto.getJSONObject(jpicto);
attributes = stupicto.getJSONObject(jattributes);
attributes.put(Picto.JSON_ATTTRS.STUPICTO_ID, stupicto.get(jid));
pictos[i] = new Picto(picto.getInt(jid),
picto.getString(juri),
attributes);
}
synchronizeImgs(pictos);
if (PCBcontext.is_user_logged())
PCBcontext.getPcbdb().setStudentVocabulary(Vocabulary.this);
else
Log.i(this.getClass().getName(), "Downloaded images ended when the user comes to logout");
Log.i(this.getClass().getName(), " Pictos downloaded: " + result.length());
} catch (JSONException e) {
StackTraceElement traces[] = e.getStackTrace();
for (StackTraceElement s : traces)
Log.e(s.getClassName() + "." + s.getFileName() + "." + s.getLineNumber(), s.toString());
Log.e(this.getClass().getName(), " Picto JSON error from server: " + stupicto.toString());
this.error(new RestapiWrapper.HTTPException("JSON Error:" + e.getMessage(), -1));
}
synchronizeImgs(pictos);
if (PCBcontext.is_user_logged()) PCBcontext.getPcbdb().setStudentVocabulary(Vocabulary.this);
else Log.i(this.getClass().getName(),"Downloaded images ended when the user comes to logout");
Log.i(this.getClass().getName(), " Pictos downloaded: " + result.length());
} catch (JSONException e) {
StackTraceElement traces[] = e.getStackTrace();
for (StackTraceElement s: traces)
Log.e(s.getClassName()+"."+s.getFileName()+"."+s.getLineNumber(),s.toString());
Log.e(this.getClass().getName(), " Picto JSON error from server: " + stupicto.toString());
this.error(new RestapiWrapper.HTTPException("JSON Error:"+e.getMessage(),-1));
}
}
}
@Override
public void result(JSONObject result) {
}
@Override
public void error(RestapiWrapper.HTTPException e) {
Log.e(this.getClass().getName(), " Server RESTAPI error: " + e.getLocalizedMessage());
if (Vocabulary.this.imgListener!=null) Vocabulary.this.imgListener.error(e);
}
});
@Override
public void result(JSONObject result) {
}
@Override
public void error(RestapiWrapper.HTTPException e) {
Log.e(this.getClass().getName(), " Server RESTAPI error: " + e.getLocalizedMessage());
if (Vocabulary.this.imgListener != null) Vocabulary.this.imgListener.error(e);
}
});
}
}
......@@ -292,7 +302,7 @@ public class Vocabulary implements Iterable<Picto> {
return index;
}
//case:categories
private Picto find_picto(int pic_cat, int row,int column) {
LinkedList<Picto> pictos_cat=this.pictos.get(pic_cat);
Picto picto=null;
......@@ -301,6 +311,15 @@ public class Vocabulary implements Iterable<Picto> {
return picto;
}
// CASE: no categories
private Picto find_picto(int row,int column) {
LinkedList<Picto> pictos_cat=this.pictos.get(Picto.NO_CATEGORY);
Picto picto=null;
for (int i=0; i<pictos_cat.size() && picto==null; i++)
if (pictos_cat.get(i).getFreeColumn()==column && pictos_cat.get(i).getFreeRow()==row) picto=pictos_cat.get(i);
return picto;
}
/**
*
* @param pic_cat Category id of the picto
......@@ -376,12 +395,13 @@ public class Vocabulary implements Iterable<Picto> {
return this.pictos.get(new Integer(Picto.NO_CATEGORY));
} else {
LinkedList<Picto> freePictos = new LinkedList<>();
for (LinkedList<Picto> category : pictos.values()) {
for (Picto picto : category) {
LinkedList<Picto> category=pictos.get(new Integer(Picto.NO_CATEGORY));
//for (Picto picto : category) {
for (Picto picto: category) {
if (picto.getFreeRow() != -1 && picto.getFreeColumn() != -1) {
freePictos.add(picto);
}
}
}
return freePictos;
}
......@@ -410,7 +430,7 @@ public class Vocabulary implements Iterable<Picto> {
public void saveLocalPicto(String url, String exp, int cat, int coord_x, int coord_y, int free_category_coord_x, int free_category_coord_y,String uri_sound,String user_avatar,String associated_person, final iLocalPicto listener) {
Picto prev_picto=find_picto(cat, coord_x,coord_y); //¿estamos reemplazanddo un picto que ya existe?
Picto prev_picto=PCBcontext.getPcbdb().getCurrentUser().has_categories() ? find_picto(cat, coord_x,coord_y) : find_picto(coord_x,coord_y); //¿estamos reemplazanddo un picto que ya existe?
if (prev_picto!=null) { //El picto ya existe
removePicto(prev_picto.get_category(),prev_picto.get_id()); //borramos el picto local actual
......
......@@ -39,7 +39,7 @@ public class NetService implements Runnable, RestapiWrapper.iSilentLogin {
private Vector<iNetServiceStatus> listeners;
private static final long restfullSynchroTimming=PCBcontext.getContext().getResources().getInteger(R.integer.netservice_force_restfull_synchro)*1000;
private long lastRestfullSynchro;
private long nextRestfullSynchro;
public NetService(int delay, iNetServiceStatus listener) {
this.updated=RestapiWrapper.ping(PCBcontext.getContext().getResources().getString(R.string.server), ping_session);
......@@ -164,7 +164,7 @@ public class NetService implements Runnable, RestapiWrapper.iSilentLogin {
Log.e(LOG_TAG, "PING JSON ERROR: " + result + " " + e.getMessage());
}
if (!updated) {
lastRestfullSynchro = new Date().getTime();
nextRestfullSynchro = new Date().getTime();
updated = true;
if (PCBcontext.is_user_logged()) //si el usuario aun no hizo login, en realidad no es necesario hacer nada
// Comprobar si hay usuario offline, para hacer login transparente
......@@ -183,13 +183,13 @@ public class NetService implements Runnable, RestapiWrapper.iSilentLogin {
//cada restfullSynchroTimming aprox. se fuerza sincronización de vocabulario y configuración de usuario
long now = new Date().getTime();
if (PCBcontext.is_user_logged()) {
if (restfullSynchroTimming > 0 && (now - lastRestfullSynchro > restfullSynchroTimming)) {
if (restfullSynchroTimming > 0 && (now>= nextRestfullSynchro)) {
Log.i(LOG_TAG, "Vocabulary request.");
PCBcontext.getVocabulary().synchronize();
synchronizeStudentAttributes();
lastRestfullSynchro = now;
nextSynchro(now+restfullSynchroTimming);
}
} else lastRestfullSynchro = new Date().getTime();
} else nextSynchro(now+restfullSynchroTimming);
}
}
......@@ -206,6 +206,13 @@ public class NetService implements Runnable, RestapiWrapper.iSilentLogin {
}
}
public void nextSynchro(long next) {
nextRestfullSynchro = next;
}
public long getSynchroTimingLength(){
return restfullSynchroTimming;
}
private void synchronizeStudentAttributes() {
int id=PCBcontext.getPcbdb().getCurrentUser().get_id_stu();
PCBcontext.getRestapiWrapper().ask("stu/" + id, new RestapiWrapper.iRestapiListener() {
......
......@@ -4,10 +4,13 @@ import android.util.Log;
import com.github.nkzawa.emitter.Emitter;
import com.yottacode.pictogram.dao.Picto;
import com.yottacode.pictogram.tools.PCBcontext;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Date;
/**
* Websocket Vocabulary Room based on Room
* @author Fernando Martinez Santiago
......@@ -50,7 +53,7 @@ public class VocabularyTalk implements Emitter.Listener {
JSONObject picto_stupicto = stu_picto.optJSONObject(param_picto);
int picto_id = picto_stupicto.getInt(param_picto_id);
int picto_cat = attrs_stu_picto!=null ? attrs_stu_picto.optInt(param_picto_cat, Picto.NO_CATEGORY) : 0;
PCBcontext.getNetService().nextSynchro(new Date().getTime()+PCBcontext.getNetService().getSynchroTimingLength()*2); //nos saltamos una sincronización para evitar que llegue antes que los websockets
Log.i(LOG_TAG, "Received message '" + action +
"' for picto " + picto_id + " (cat " + picto_cat + ", picto: " + picto_stupicto);
for (iVocabularyListener listener: this.listeners)
......
......@@ -78,7 +78,7 @@ public final class PCBcontext {
public void change(User updatedStudent) {
PCBcontext.getDevice().insertUser(updatedStudent);
if (updatedStudent.is_picto_size_big()!=getPcbdb().getCurrentUser().is_picto_size_big() || updatedStudent.has_categories()!=getPcbdb().getCurrentUser().has_categories())
PCBcontext.getNetService().restart_app(true);
PCBcontext.getNetService().restart_app(false);
else {
PCBcontext.getPcbdb().setCurrentUser(updatedStudent);
PCBcontext.getNetService().getNetServiceDevice().updateUserConfig(updatedStudent);
......
......@@ -21,6 +21,7 @@ android {
resValue "bool","NotifyAllwaysVisible","false"
resValue "string", "VersionManagerClass", "com.yottacode.pictogram.supervisor_tablet.net.VersionManager"
resValue "string","apk","pictograms.apk"
resValue "string","google_play_apk","https://play.google.com/store/apps/details?id=com.yottacode.supervisor_tablet"
// signingConfig signingConfigs.config
}
productFlavors {
......
......@@ -26,8 +26,7 @@ public class VersionManager implements iVersionManager {
public void newVersionAlert(final float version, final Context context, final float vnew) {
final SpannableString s = new SpannableString(context.getResources().getString(R.string.server)
+ "/" + context.getResources().getString(com.yottacode.pictogram.R.string.apk));
final SpannableString s = new SpannableString(context.getResources().getString(R.string.google_play_apk));
final TextView tx1 = new TextView(context);
tx1.setText("\t"+context.getResources().getString(R.string.new_version_detail) +
......
......@@ -10,7 +10,6 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
......@@ -538,7 +537,7 @@ public class PictogramActivity extends Activity implements VocabularyTalk.iVocab
}
} else {
if (p.getFreeColumn() != -1 && p.getFreeRow() != -1
&& p.get_column() < maxRows && p.get_row() < maxColumns) {
&& p.getFreeColumn() < maxRows && p.getFreeRow() < maxColumns) {
mp[p.getFreeColumn()][p.getFreeRow()] = p;
}
}
......@@ -869,7 +868,8 @@ public class PictogramActivity extends Activity implements VocabularyTalk.iVocab
if (p == null) {
// No tengo pictograma. Abro una nueva ventana de selección desde el Carrete del device si no es categoria
if (getCurrentCategory() != null || !PCBcontext.getPcbdb().getCurrentUser().has_categories()) {
new PictoMenu(PictogramActivity.this).createMenuForNewPicto(position % maxColumns, (int) (position / maxColumns), currentCategory.get_id());
int cat = getCurrentCategory() != null ? currentCategory.get_id() : Picto.NO_CATEGORY;
new PictoMenu(PictogramActivity.this).createMenuForNewPicto(position % maxColumns, (int) (position / maxColumns), cat);
} else
Toast.makeText(PictogramActivity.this, PictogramActivity.this.getResources().getString(R.string.notNewCats), Toast.LENGTH_SHORT).show();
......
......@@ -71,39 +71,42 @@ public class SessionActivity extends FragmentActivity implements ListInstruction
}
private void evaluateMsg(final int msg_pos, final String evaluation_value, final int evaluation_translation, final int evaluation_bitmap) {
final SessionFragment sessionFragment = (SessionFragment) getSupportFragmentManager().findFragmentByTag(SessionActivity.FRAGMENT_SESSION);
final int currentMsgId=SessionActivity.this.msgs.get(msg_pos);
SessionWrapper.evaluateTry(currentMsgId, msg_pos==this.msgs.size()-1, evaluation_value, new SessionWrapper.iTryUpdated() {
@Override
public void update(int next_try_id) {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),evaluation_bitmap);
sessionFragment.evaluateMsg(bitmap,getString(evaluation_translation),msg_pos);
addLogMsg("#"+(msg_pos<9 ? "0" : "")+(msg_pos+1)+sessionFragment.get_msg_text(msg_pos));
if (!msgs.containsValue(next_try_id))
new_try(sessionFragment, next_try_id);
if (evaluation_value!=null && msg_pos==msgs.size()-1){
SessionWrapper.newTry(id_session, new SessionWrapper.iTryUpdated() {
@Override
public void update(int id) {
int pos_newmsg = sessionFragment.newMsg();
msgs.put(pos_newmsg, id);
addLogMsg(getString(R.string.session_log_newtry));
}
@Override
public void error(String error) {
addLogMsg(getString(R.string.session_error));
}
});
if (sessionFragment.get_current_msg_text().trim().length()>0) //no se permiten trys vacios
SessionWrapper.evaluateTry(currentMsgId, msg_pos==this.msgs.size()-1, evaluation_value, new SessionWrapper.iTryUpdated() {
@Override
public void update(int next_try_id) {
addLogMsg("añadiendo "+ sessionFragment.get_current_msg_text()+".");
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),evaluation_bitmap);
sessionFragment.evaluateMsg(bitmap,getString(evaluation_translation),msg_pos);
addLogMsg("#"+(msg_pos<9 ? "0" : "")+(msg_pos+1)+sessionFragment.get_msg_text(msg_pos));
if (!msgs.containsValue(next_try_id))
new_try(sessionFragment, next_try_id);
if (evaluation_value!=null && msg_pos==msgs.size()-1){
SessionWrapper.newTry(id_session, new SessionWrapper.iTryUpdated() {
@Override
public void update(int id) {
int pos_newmsg = sessionFragment.newMsg();
msgs.put(pos_newmsg, id);
addLogMsg(getString(R.string.session_log_newtry));
}
@Override
public void error(String error) {
addLogMsg(getString(R.string.session_error));
}
});
}
}
}
@Override
public void error(String error) {
addLogMsg(getString(R.string.session_error)+":"+error);
Log.e(LOG_TAG,"server error:"+error+" when updating try "+currentMsgId+" to "+evaluation_value);
}
});
@Override
public void error(String error) {
addLogMsg(getString(R.string.session_error)+":"+error);
Log.e(LOG_TAG,"server error:"+error+" when updating try "+currentMsgId+" to "+evaluation_value);
}
});
......
......@@ -98,6 +98,6 @@ public class NetServiceTablet implements NetService.iNetServiceDevice {
}
public void setPictogramActivity(PictogramActivity pictogramActivity) {this.pictogramActivity=pictogramActivity;}
public void updateUserConfig(User user) {
this.pictogramActivity.setConfig();
if (this.pictogramActivity!=null) this.pictogramActivity.setConfig();
}
}
......@@ -97,27 +97,28 @@
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="support-v4-24.2.1" level="project" />
<orderEntry type="library" exported="" name="support-compat-24.2.1" level="project" />
<orderEntry type="library" exported="" name="support-media-compat-24.2.1" level="project" />
<orderEntry type="library" exported="" name="animated-vector-drawable-24.2.1" level="project" />
<orderEntry type="library" exported="" name="support-fragment-24.2.1" level="project" />
<orderEntry type="library" exported="" name="play-services-base-9.2.1" level="project" />
<orderEntry type="library" exported="" name="androidasync-2.1.9" level="project" />
<orderEntry type="library" exported="" name="play-services-clearcut-9.2.1" level="project" />
<orderEntry type="library" exported="" name="android-gif-drawable-1.1.7" level="project" />
<orderEntry type="library" exported="" name="support-v4-23.0.0" level="project" />
<orderEntry type="library" exported="" name="support-media-compat-24.2.1" level="project" />
<orderEntry type="library" exported="" name="play-services-gcm-9.2.1" level="project" />
<orderEntry type="library" exported="" name="play-services-auth-base-9.2.1" level="project" />
<orderEntry type="library" exported="" name="support-core-ui-24.2.1" level="project" />
<orderEntry type="library" exported="" name="play-services-base-9.2.1" level="project" />
<orderEntry type="library" exported="" name="play-services-gass-9.2.1" level="project" />
<orderEntry type="library" exported="" name="play-services-iid-9.2.1" level="project" />
<orderEntry type="library" exported="" name="appcompat-v7-24.2.1" level="project" />
<orderEntry type="library" exported="" name="support-vector-drawable-24.2.1" level="project" />
<orderEntry type="library" exported="" name="support-core-utils-24.2.1" level="project" />
<orderEntry type="library" exported="" name="androidasync-2.1.9" level="project" />
<orderEntry type="library" exported="" name="play-services-clearcut-9.2.1" level="project" />
<orderEntry type="library" exported="" name="play-services-basement-9.2.1" level="project" />
<orderEntry type="library" exported="" name="play-services-tasks-9.2.1" level="project" />
<orderEntry type="library" exported="" name="support-annotations-24.2.1" level="project" />
<orderEntry type="library" exported="" name="play-services-auth-9.2.1" level="project" />
<orderEntry type="library" exported="" name="play-services-ads-9.2.1" level="project" />
<orderEntry type="library" exported="" name="ion-2.1.9" level="project" />
<orderEntry type="library" exported="" name="support-v4-23.0.0" level="project" />
<orderEntry type="library" exported="" name="play-services-ads-lite-9.2.1" level="project" />
<orderEntry type="module" module-name="commonlibrary" exported="" />
<orderEntry type="library" exported="" name="android-android-24" level="project" />
......
......@@ -10,7 +10,7 @@ module.exports = {
/**
* Return all subcategories from a category using the language of the specified supervisor.
* If 0 is specified as category all categories without supercategory will be returned.
* @param {request} req {} (with supervisorId and categoryId as url parameters)
* @param {request} req {} (with lang and categoryId as url parameters)
* @param {response} res
* [
* {
......@@ -31,29 +31,20 @@ module.exports = {
* ]
*/
categories: function (req, res) {
Supervisor.findOne({ id: req.params.id }).then(function (supervisor) {
if (supervisor) {
PictoCat
.find({ id_supercat: req.params.id_cat })
.populate('exps', { lang: supervisor.lang })
.then(function (categories) {
res.ok(categories);
})
.catch(function (err) {
throw err;
});
} else {
res.badRequest();
}
})
.catch(function (err) {
res.serverError(err);
});
PictoCat
.find({ id_supercat: req.params.id_cat })
.populate('exps', { lang: req.params.lang })
.then(function (categories) {
res.ok(categories);
})
.catch(function (err) {
return res.serverError();
});
},
/**
* Return all pictos from a category using the language of the specified supervisor.
* @param {request} req {} (with supervisorId and categoryId as url parameters)
* @param {request} req {} (with lang and categoryId as url parameters)
* @param {response} res
* [
* {
......@@ -83,45 +74,37 @@ module.exports = {
if (req.params.id_cat == 0)
return res.ok(l);
Supervisor.findOne({ id: req.params.id }).then(function (supervisor) {
if (supervisor) {
Picto.find({ category: req.params.id_cat })
.populate('expressions', { lang: supervisor.lang })
.then(function (pictos) {
async.eachSeries(pictos, function(picto, next_cb) {
// check picto has expressions associated in student language
if (picto.expressions.length == 0 || picto.expressions[0].text.length == 0)
return next_cb();
// check picto image is available
picto.imageFileExists((found) => {
if (found) {
l.push(picto);
next_cb();
}
else
next_cb();
});
},
function (err) { // loop has end
if (err) throw err;
sails.log.debug(pictos.length + " pictos sent for category " + req.params.id_cat + " in language " + supervisor.lang);
return res.ok(l);
}); // end async.eachSeries
})
.catch(() => res.badRequest());
} else {
return res.badRequest();
}
Picto.find({ category: req.params.id_cat })
.populate('expressions', { lang: req.params.lang })
.then(function (pictos) {
async.eachSeries(pictos, function(picto, next_cb) {
// check picto has expressions associated in student language
if (picto.expressions.length == 0 || picto.expressions[0].text.length == 0)
return next_cb();
// check picto image is available
picto.imageFileExists((found) => {
if (found) {
l.push(picto);
next_cb();
}
else next_cb();
});
},
function (err) { // loop has end
if (err) throw err;
sails.log.debug(pictos.length + " pictos sent for category " + req.params.id_cat + " in language " + req.params.lang);
return res.ok(l);
}); // end async.eachSeries
})
.catch(() => res.serverError());
.catch(() => res.badRequest());
},
/**
* Return all pictos from a category and subcategoriesusing the language
* of the specified supervisor.
* @param {request} req {} (with supervisorId and categoryId as url parameters)
* @param {request} req {} (with lang and categoryId as url parameters)
* @param {response} res
* [
* {
......@@ -147,55 +130,41 @@ module.exports = {
var l = [];
var fs = require('fs');
// return empty for category 0 (that represents category pictos and all custom pictos)
// if (req.params.id_cat == 0)
// return res.ok(l);
Supervisor.findOne({ id: req.params.id }).then(function (supervisor) {
if (supervisor) {
PictoCatTree
.find({select: ['id_cat'], id_ancestor: req.params.id_cat })
.then(function (categories) {
var filtered = [Number(req.params.id_cat)]; // Category itself
for(var i =0; i<categories.length;i++){ //All subcategories
filtered.push(categories[i].id_cat);
}
Picto.find({ category: filtered })
.paginate({ page: req.params.page, limit: req.params.limit})
.populate('expressions', { lang: supervisor.lang })
.then(function (pictos) {
async.eachSeries(pictos, function(picto, next_cb) {
// check picto has expressions associated in student language
if (picto.expressions.length == 0 || picto.expressions[0].text.length == 0)
return next_cb();
// check picto image is available
picto.imageFileExists((found) => {
if (found) {
l.push(picto);
next_cb();
}
else
next_cb();
});
},
function (err) { // loop has end
if (err) throw err;
sails.log.debug(pictos.length + " pictos sent for category " + req.params.id_cat + " in language " + supervisor.lang);
return res.ok(l);
}); // end async.eachSeries
})
.catch(() => res.badRequest());
return categories;
})
.catch(function (err) {
throw err;
});
} else {
return res.badRequest();
PictoCatTree
.find({select: ['id_cat'], id_ancestor: req.params.id_cat })
.then(function (categories) {
var filtered = [Number(req.params.id_cat)]; // Category itself
for(var i =0; i<categories.length;i++){ //All subcategories
filtered.push(categories[i].id_cat);
}
Picto.find({ category: filtered })
.paginate({ page: req.params.page, limit: req.params.limit})
.populate('expressions', { lang: req.params.lang })
.then(function (pictos) {
async.eachSeries(pictos, function(picto, next_cb) {
// check picto has expressions associated in student language
if (picto.expressions.length == 0 || picto.expressions[0].text.length == 0)
return next_cb();
// check picto image is available
picto.imageFileExists((found) => {
if (found) {
l.push(picto);
next_cb();
}
else
next_cb();
});
},
function (err) { // loop has end
if (err) throw err;
sails.log.debug(pictos.length + " pictos sent for category " + req.params.id_cat + " in language " + req.params.lang);
return res.ok(l);
}); // end async.eachSeries
})
.catch(() => res.badRequest());
return categories;
})
.catch(() => res.serverError());
},
......@@ -203,7 +172,7 @@ module.exports = {
/**
* Return own or public pictos using a search string from category
* and subcategories using the language of the specified supervisor.
* @param {request} req {} (with supervisorId and categoryId as url parameters)
* @param {request} req {} (with supervisorId, lang and categoryId as url parameters)
* @param {response} res
* [
* {
......@@ -226,34 +195,25 @@ module.exports = {
* ]
*/
fromSearch: function (req, res) {
Supervisor.findOne({ id: req.params.id }).then(function (supervisor) {
if (supervisor) {
if (req.params.id_cat == 0){ //Search in all categories
getPictos(0, supervisor.lang, supervisor.id);
}else{//Get selected category and subcategories
PictoCatTree
.find({select: ['id_cat'], id_ancestor: req.params.id_cat })
.then(function (categories) {
var filtered = [Number(req.params.id_cat)]; //Category itself
for(var i =0; i<categories.length;i++){ //All subcategories
filtered.push(categories[i].id_cat);
}
getPictos(filtered, supervisor.lang, supervisor.id);
})
.catch(function (err) {
throw err;
});
if (req.params.id_cat == 0){ //Search in all categories
getPictos(0);
} else { //Get selected category and subcategories
PictoCatTree
.find({select: ['id_cat'], id_ancestor: req.params.id_cat })
.then(function (categories) {
var filtered = [Number(req.params.id_cat)]; //Category itself
for(var i =0; i<categories.length;i++) { //All subcategories
filtered.push(categories[i].id_cat);
}
} else {
return res.badRequest();
}
})
.catch(() => res.serverError());
getPictos(filtered);
})
.catch(() => res.serverError());
}
//
// Get pictos within specified categories
//
function getPictos(categories, lang, sup_id){
function getPictos(categories, lang){
var l = [];
var fs = require('fs');
......@@ -261,10 +221,10 @@ module.exports = {
var params = [];
if(typeof categories == "object" ){ //Is an array
sql="SELECT `picto_exp`.`id`, `picto_exp`.`id_pic`, `picto_exp`.`lang`, `picto_exp`.`text`, `picto`.`id`, `picto`.`uri`, `picto`.`id_src`, `picto`.`id_owner`, `picto`.`id_cat` FROM `picto_exp` INNER JOIN `picto` ON `picto_exp`.`id_pic` = `picto`.`id` WHERE `picto_exp`.`lang`=? AND `picto_exp`.`text` LIKE ? AND (`picto`.`id_owner` IS NULL OR `picto`.`id_owner`=?) AND `picto`.`id_src`=? AND `picto`.`id_cat` IN (?);";
params = [lang,'%'+req.params.text+'%', sup_id, req.params.source, categories];
params = [req.params.lang,'%'+req.params.text+'%', req.params.sup_id, req.params.source, categories];
}else{
sql= "SELECT `picto_exp`.`id`, `picto_exp`.`id_pic`, `picto_exp`.`lang`, `picto_exp`.`text`, `picto`.`id`, `picto`.`uri`, `picto`.`id_src`, `picto`.`id_owner`, `picto`.`id_cat` FROM `picto_exp` INNER JOIN `picto` ON `picto_exp`.`id_pic` = `picto`.`id` WHERE `picto_exp`.`lang`=? AND `picto_exp`.`text` LIKE ? AND (`picto`.`id_owner` IS NULL OR `picto`.`id_owner`=?) AND `picto`.`id_src`=?;";
params = [lang,'%'+req.params.text+'%', sup_id, req.params.source];
params = [req.params.lang,'%'+req.params.text+'%', req.params.sup_id, req.params.source];
}
// PictoExp.find({lang: lang, text: { like: '%'+req.params.text+'%'}})
......@@ -335,40 +295,33 @@ module.exports = {
var fs = require('fs');
var cat = req.params.id_cat;
Supervisor.findOne({ id: req.params.id }).then(function (supervisor) {
if (supervisor) {
Picto.find({ source: 1})
.paginate({page: req.params.page, limit:req.params.limit})
.populate('expressions', { lang: supervisor.lang })
.then(function (pictos) {
async.eachSeries(pictos, function(picto, next_cb) {
// check picto has expressions associated in student language
if (picto.expressions.length == 0 || picto.expressions[0].text.length == 0)
return next_cb();
// check picto image is available
picto.imageFileExists((found) => {
if (found) {
l.push(picto);
next_cb();
}
else
next_cb();
});
},
function (err) { // loop has end
if (err) throw err;
sails.log.debug(pictos.length + " pictos sent from SymbolStx in language " + supervisor.lang);
return res.ok(l);
}); // end async.eachSeries
})
.catch(() => res.badRequest());
} else {
return res.badRequest();
}
Picto.find({ source: 1})
.paginate({page: req.params.page, limit:req.params.limit})
.populate('expressions', { lang: req.params.lang })
.then(function (pictos) {
async.eachSeries(pictos, function(picto, next_cb) {
// check picto has expressions associated in student language
if (picto.expressions.length == 0 || picto.expressions[0].text.length == 0)
return next_cb();
// check picto image is available
picto.imageFileExists((found) => {
if (found) {
l.push(picto);
next_cb();
}
else
next_cb();
});
},
function (err) { // loop has end
if (err) throw err;
sails.log.debug(pictos.length + " pictos sent from SymbolStx in language " + req.params.lang);
return res.ok(l);
}); // end async.eachSeries
})
.catch(() => res.serverError());
.catch(() => res.badRequest());
},
/**
......@@ -399,40 +352,32 @@ module.exports = {
var l = [];
var fs = require('fs');
Supervisor.findOne({ id: req.params.id }).then(function (supervisor) {
if (supervisor) {
Picto.find({ source: 3})
.paginate({page: req.params.page, limit:req.params.limit})
.populate('expressions', { lang: supervisor.lang })
.then(function (pictos) {
async.eachSeries(pictos, function(picto, next_cb) {
// check picto has expressions associated in student language
if (picto.expressions.length == 0 || picto.expressions[0].text.length == 0)
return next_cb();
// check picto image is available
picto.imageFileExists((found) => {
if (found) {
l.push(picto);
next_cb();
}
else
next_cb();
});
},
function (err) { // loop has end
if (err) throw err;
sails.log.debug(pictos.length + " pictos sent from Arasaac in language " + supervisor.lang);
return res.ok(l);
}); // end async.eachSeries
})
.catch(() => res.badRequest());
} else {
return res.badRequest();
}
Picto.find({ source: 3})
.paginate({page: req.params.page, limit:req.params.limit})
.populate('expressions', { lang: req.params.lang })
.then(function (pictos) {
async.eachSeries(pictos, function(picto, next_cb) {
// check picto has expressions associated in student language
if (picto.expressions.length == 0 || picto.expressions[0].text.length == 0)
return next_cb();
// check picto image is available
picto.imageFileExists((found) => {
if (found) {
l.push(picto);
next_cb();
}
else next_cb();
});
},
function (err) { // loop has end
if (err) throw err;
sails.log.debug(pictos.length + " pictos sent from Arasaac in language " + req.params.lang);
return res.ok(l);
}); // end async.eachSeries
})
.catch(() => res.serverError());
.catch(() => res.badRequest());
},
/**
......
......@@ -1189,75 +1189,47 @@ module.exports = {
/**
* Upload a custom sound associated to a picto
* @param {request} req
* id_stu,
* id_picto,
* attributes: { @see StuPicto.getValidAttributes() }
* id_stu_picto,
*
* @param {response} res
* {
* id: <stu_picto ID>,
* student: <student ID>,
* attributes: {
* id_cat: categoryId or null,
* coord_x: 1 .. 5 or null,
* coord_y: 1 .. 10 or null,
* free_category_coord_x: 0 .. 4 or null,
* free_category_coord_y: 0 .. 9 or null,
* status: '[invisible]/enabled/disabled',
* highlight: true/[false],
* color: any valid HEX color or [null],
* expression: 'custom expression',
* legend: true/[false],
* uri_sound: 'path of sound associated',
* user_avatar:
* },
* picto: {
* id: <pictoID>,
* source: <sourceID>,
* owner: <ownerID> or null,
* id: <pictoID>,
* uri: <URL to image>,
* category: <categoryID>
* }
* }
* stu_picto
* }
*/
upload_sound: function (req, res) {
Supervisor.findOne({ id: req.body.owner }).then(function (supervisor) {
var soundFileName;
var soundDirectory = sails.config.pictogram.paths.pictoSoundDirectory;
if (!supervisor)
throw new Error("No supervisor found");
soundFileName = sails.config.pictogram.paths.getSupervisorCustomPictoFileName(supervisor.id)
+ "_sound";
sails.log.debug("Uploading sound with FileName: " + soundFileName);
req.file('file').upload({
maxBytes: 1048576,
dirname: soundDirectory,
saveAs: soundFileName
},function whenDone(err, uploadedFiles) {
var fs = require('fs');
if (err || (uploadedFiles.length === 0))
return res.serverError("Error uploading " + err ? err : "");
StuPicto.findOne({ id: req.body.id})
.then(picto => {
return res.ok(picto);
})
.populate('uri_sound',soundFileName)
.catch(err => {
fs.unlink(uploadedFiles[0].fd);
return res.serverError("Error uploading " + err);
var soundFileName;
var soundDirectory = sails.config.pictogram.paths.pictoSoundDirectory;
console.log("Llega aqui 1");
soundFileName = sails.config.pictogram.paths.getCustomPictoSoundFilename(req.params.id_stu_picto);
console.log("Llega aqui 2");
req.file('file').upload({
maxBytes: 1048576,
dirname: soundDirectory,
saveAs: soundFileName
}, function whenDone(err, uploadedFiles) {
console.log("Llega aqui 3");
var fs = require('fs');
if (err || (uploadedFiles.length === 0))
return res.serverError("Error uploading " + err ? err : "");
console.log("Llega aqui 4");
StuPicto.findOne({ id: req.params.id_stu_picto})
.then(sp => {
console.log("Picto encontrado")
sp.attributes.uri_sound = soundFileName;
sp.save(function (err) {
if (err) throw err;
return res.ok(sp);
});
})
.catch(err => {
fs.unlink(uploadedFiles[0].fd);
return res.serverError("Error uploading " + err);
});
})
.catch(function (err) {
return res.serverError("Error uploading sound: " + err);
});
},
// ***************************************************************
// WEBSOCKETS
// ***************************************************************
......
......@@ -591,7 +591,7 @@ module.exports = {
PictoExp.findOne({id_pic: sp.picto.id, lang: sp.student.lang})
.then(pe => {
if (typeof sp.attributes.expression == 'undefined' || sp.attributes.expression == null)
sp.attributes.expression = pe.text;
sp.attributes.expression = pe.text;
sp.student = sp.student.id;
delete sp.picto.expressions;
cb(null,sp);
......
......@@ -51,10 +51,10 @@ dashboardControllers.controller('AddPictoCtrl', function (
var request = "";
if(categoryId == 0){
//Request page X from all pictos (symbolstx)
request = config.backend + '/sup/' + supervisor.id +
request = config.backend + '/picto/' + student.lang +
'/pic_fromSymbolStx/page/'+$scope.page+'/limit/'+$scope.limit;
}else{
request = config.backend + '/sup/' + supervisor.id +
request = config.backend + '/picto/' + student.lang +
'/pic_fromCatSubcat/category/'+categoryId+'/page/'+$scope.page+'/limit/'+$scope.limit;
}
$http.get(request)
......@@ -96,7 +96,7 @@ dashboardControllers.controller('AddPictoCtrl', function (
var request = "";
//Request page X from all pictos (symbolstx)
request = config.backend + '/sup/' + supervisor.id +
request = config.backend + '/picto/' + student.lang +
'/pic_fromArasaac/page/'+$scope.page+'/limit/'+$scope.limit;
$http.get(request)
......@@ -142,7 +142,7 @@ dashboardControllers.controller('AddPictoCtrl', function (
//
$scope.load_category = function (categoryId){
$scope.page = 1;
$http.get(config.backend+'/sup/'+ supervisor.id +'/pic_categories/' + categoryId)
$http.get(config.backend + '/picto/' + student.lang + '/pic_categories/' + categoryId)
.success(function(data, status, headers, config) {
// Add to list
if (data && $scope.source == 'symbolstx'){
......@@ -335,16 +335,16 @@ dashboardControllers.controller('AddPictoCtrl', function (
if($scope.source == "symbolstx"){
if($scope.breadcrumbs.length == 1) {
//Request page X from all pictos (symbolstx)
request = config.backend + '/sup/' + supervisor.id +
request = config.backend + '/picto/' + student.lang +
'/pic_fromSymbolStx/page/'+$scope.page+'/limit/'+$scope.limit;
}else{
request = config.backend + '/sup/' + supervisor.id +
request = config.backend + '/picto/' + student.lang +
'/pic_fromCatSubcat/category/'+$scope.breadcrumbs[$scope.breadcrumbs.length-1].id
+'/page/'+$scope.page+'/limit/'+$scope.limit;
}
}else if($scope.source == "arasaac"){
//Request page X from all pictos (symbolstx)
request = config.backend + '/sup/' + supervisor.id +
request = config.backend + '/picto/' + student.lang +
'/pic_fromArasaac/page/'+$scope.page+'/limit/'+$scope.limit;
}
......@@ -399,7 +399,7 @@ dashboardControllers.controller('AddPictoCtrl', function (
}else if($scope.source == "arasaac"){
source = 3;
}
request = config.backend + '/sup/' + supervisor.id +
request = config.backend + '/picto/' + student.lang + '/' + supervisor.id +
'/pic_fromSearch/'+$scope.srch_term_picto+'/category/'+category+
'/source/'+source;
......
......@@ -75,6 +75,18 @@ module.exports.pictogram = {
.replace(/\W/g, '') + ".jpg";
},
_getRandomSoundFileName: function (randomString, randomNumber) {
var bcrypt = require('bcrypt-nodejs');
var randomDate = (new Date())
.getTime();
var randomFloat = Math.random();
return bcrypt.hashSync(
[randomString, randomDate, randomNumber, randomFloat].join(''),
bcrypt.genSaltSync()
)
.replace(/\W/g, '') + "_sound.mp3";
},
/**
* Gets the supervisor avatar filename
* @param {supervisorId} supervisorId
......@@ -109,9 +121,21 @@ module.exports.pictogram = {
'SUPERVISOR_CUSTOM_PICTO',
supervisorId
);
},
/**
* Gets the supervisor custom picto filename
* @param {supervisorId} supervisorId supervisorId
* @return {string} fileName
*/
getCustomPictoSoundFilename: function (supervisorId) {
return sails.config.pictogram.paths._getRandomSoundFileName(
'SUPERVISOR_CUSTOM_PICTO',
supervisorId
);
}
},
// TODO: errores should have a code (number) and a name (string) like "TokenExpired", "UserNotFound"...
error_codes: {
'DUPLICATED_PICTO': 1,
......
......@@ -105,7 +105,7 @@ module.exports.policies = {
login: true,
create: ['tokenAuth', 'isSupAdmin'],
upload: ['tokenAuth'],
upload_sound: ['tokenAuth', 'isSupervisorOfStudent'],
upload_sound: ['tokenAuth'],
add_picto: ['tokenAuth', 'isSupervisorOfStudent'],
subscribe: ['tokenAuth'],
unsubscribe: true,
......
......@@ -59,6 +59,13 @@ module.exports.routes = {
'GET /office/get/:id': 'OfficeController.get',
'GET /office/get/:id/supervisors': 'OfficeController.supervisors',
'GET /picto/:lang/pic_categories/:id_cat': 'PictoController.categories',
'GET /picto/:lang/pic_fromcategory/:id_cat': 'PictoController.fromcategory',
'GET /picto/:lang/pic_fromSymbolStx/page/:page/limit/:limit': 'PictoController.fromSymbolStx',
'GET /picto/:lang/pic_fromArasaac/page/:page/limit/:limit': 'PictoController.fromArasaac',
'GET /picto/:lang/pic_fromCatSubcat/category/:id_cat/page/:page/limit/:limit': 'PictoController.fromCatSubcat',
'GET /picto/:lang/:id_sup/pic_fromSearch/:text/category/:id_cat/source/:source': 'PictoController.fromSearch',
'POST /picto/upload': 'PictoController.upload',
'POST /picto/tag': 'PictoController.add_tag',
'POST /picto/exp': 'PictoController.change_exp',
......@@ -74,6 +81,7 @@ module.exports.routes = {
'GET /stu/:id_stu/tutors': 'StudentController.tutors',
'POST /stu/:id_stu/sup/:id_sup': 'StudentController.link_supervisor',
'GET /stu/:id_stu/pictos': 'StudentController.pictos',
'GET /stu/:id_stu/methods': 'StudentController.methods',
'GET /stu/:id_stu/lasttries': 'StudentController.lasttries',
'GET /stu/:id_stu/tries': 'StudentController.tries',
......@@ -87,7 +95,7 @@ module.exports.routes = {
'POST /stu/login': 'StudentController.login',
'POST /stu': 'StudentController.create',
'POST /stu/upload': 'StudentController.upload',
'POST /stu/:id_stu/upload/:id_picto': 'StudentController.upload_sound',
'POST /stu/upload/:id_stu_picto': 'StudentController.upload_sound',
'POST /stu/:id_stu/picto/:id_picto': 'StudentController.add_picto',
'POST /stu/subscribe': 'StudentController.subscribe',
'POST /stu/unsubscribe': 'StudentController.unsubscribe',
......@@ -105,12 +113,7 @@ module.exports.routes = {
'GET /sup/all': 'SupervisorController.list',
'GET /sup/:id/students': 'SupervisorController.students',
'GET /sup/:id/pictos': 'SupervisorController.pictos',
'GET /sup/:id/pic_categories/:id_cat': 'PictoController.categories',
'GET /sup/:id/pic_fromcategory/:id_cat': 'PictoController.fromcategory',
'GET /sup/:id/pic_fromSymbolStx/page/:page/limit/:limit': 'PictoController.fromSymbolStx',
'GET /sup/:id/pic_fromArasaac/page/:page/limit/:limit': 'PictoController.fromArasaac',
'GET /sup/:id/pic_fromCatSubcat/category/:id_cat/page/:page/limit/:limit': 'PictoController.fromCatSubcat',
'GET /sup/:id/pic_fromSearch/:text/category/:id_cat/source/:source': 'PictoController.fromSearch',
'GET /sup/email/:email': 'SupervisorController.getByEmail',
'GET /sup/changepass/:email': 'SupervisorController.request_change_password',
'GET /sup/arasaac_license/:id': 'SupervisorController.accept_arasaac',
......
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 sign in to comment