Commit c1ee16d1 by Arturo Montejo Ráez

Merge branch 'develop' of http://gitlab.ujaen.es/yotta/pictogram into develop

parents cdb09a12 120db4de
Showing with 695 additions and 223 deletions
......@@ -50,6 +50,8 @@ public class Picto extends Img {
public static String EXPRESSION = "expression";
public static String MIRROR = "mirror";
public static String LEGEND = "legend";
public static String URI_SOUND = "uri_sound";
public static String USER_AVATAR = "user_avatar";
}
......@@ -88,7 +90,7 @@ public class Picto extends Img {
Log.e(LOG_TAG,e.getMessage());
}
}
public Picto(int id, String url, String translation, int cat, int row, int column, int freeRow, int freeColumn, int stupicto_id) throws JSONException {
public Picto(int id, String url, String translation, int cat, int row, int column, int freeRow, int freeColumn, int stupicto_id, String uri_sound, String user_avatar) throws JSONException {
this(id, url, new JSONObject()
.put(JSON_ATTTRS.CATEGORY, cat)
.put(JSON_ATTTRS.COLUMN, column)
......@@ -98,7 +100,10 @@ public class Picto extends Img {
.put(JSON_ATTTRS.STATUS, JSON_ATTTR_STATUS_VALUES.ENABLED)
.put(JSON_ATTTRS.LEGEND,JSON_ATTTR_LEGEND_VALUES.NONE)
.put(JSON_ATTTRS.STUPICTO_ID,stupicto_id)
.put(JSON_ATTTRS.EXPRESSION,translation));
.put(JSON_ATTTRS.EXPRESSION,translation)
.put(JSON_ATTTRS.URI_SOUND,uri_sound)
.put(JSON_ATTTRS.USER_AVATAR,user_avatar)
);
}
public Picto(int id, String url,String translation, String attributes) throws JSONException {
this(id, url, new JSONObject(attributes).put(JSON_ATTTRS.EXPRESSION,translation));
......@@ -341,7 +346,21 @@ public class Picto extends Img {
}
}
/**
*
* @return the uri of associated sound of the picto
*/
public String getUriSound(){
return this.attributes.optString(JSON_ATTTRS.URI_SOUND);
}
/**
*
* @return the associated user avatar of the picto
*/
public String getUserAvatar(){
return this.attributes.optString(JSON_ATTTRS.USER_AVATAR);
}
/**
* A picto is a category iif:
......
......@@ -399,7 +399,7 @@ public class Vocabulary implements Iterable<Picto> {
/*
* It saves locally a new picto obtained from the PCB
*/
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, final iLocalPicto listener) {
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, final iLocalPicto listener) {
Picto prev_picto=find_picto(cat, coord_x,coord_y); //¿estamos reemplazanddo un picto que ya existe?
......@@ -411,7 +411,7 @@ public class Vocabulary implements Iterable<Picto> {
int id=PCBcontext.getDevice().getNextLocalPictoID();
try {
final Picto picto = new Picto(id, url, exp, cat, coord_x, coord_y, free_category_coord_x, free_category_coord_y, prev_picto!=null ? prev_picto.get_stupicto_id() : Picto.STUPICTO_NULL);
final Picto picto = new Picto(id, url, exp, cat, coord_x, coord_y, free_category_coord_x, free_category_coord_y,prev_picto!=null ? prev_picto.get_stupicto_id() : Picto.STUPICTO_NULL,uri_sound,user_avatar);
addPicto(picto, ImgDownloader.tsource.local, new ImgDownloader.iImgDownloaderListener() {
@Override
public void loadComplete() {
......
......@@ -50,7 +50,7 @@ public class PictoUploader {
bmp=img.get_bitmap(PCBcontext.getContext());
Log.i(LOG_TAG, "Uploading Picto img " + img.file_name() + " from " + img.get_type() + "- Size:" + bmp.getWidth() + " " + bmp.getHeight());
/*Log.i(LOG_TAG, "Uploading Picto img " + img.file_name() + " from " + img.get_type() + "- Size:" + bmp.getWidth() + " " + bmp.getHeight());*/
File file = img.file(PCBcontext.getContext());
......
......@@ -31,4 +31,5 @@ dependencies {
compile project(':commonlibrary')
compile 'com.android.support:appcompat-v7:24.2.1'
compile 'com.android.support:support-v4:24.2.1'
compile 'pl.droidsonroids.gif:android-gif-drawable:1.1.+'
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yottacode.pictogram.tabletlibrary">
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<application
android:allowBackup="true"
android:label="@string/app_name"
......
package com.yottacode.pictogram.tabletlibrary.gui.communicator;
import com.yottacode.pictogram.tabletlibrary.R;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.ColorRes;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.ImageView;
public class BotonCircular extends android.support.v7.widget.AppCompatImageView {
private static final int PRESSED_COLOR_LIGHTUP = 255 / 25;
private static final int PRESSED_RING_ALPHA = 75;
private static final int DEFAULT_PRESSED_RING_WIDTH_DIP = 4;
private static final int ANIMATION_TIME_ID = android.R.integer.config_shortAnimTime;
private int centerY;
private int centerX;
private int outerRadius;
private int pressedRingRadius;
private Paint circlePaint;
private Paint focusPaint;
private float animationProgress;
private int pressedRingWidth;
private int defaultColor;
private int pressedColor;
private ObjectAnimator pressedAnimator;
public BotonCircular(Context context) {
super(context);
init(context, null);
}
public BotonCircular(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public BotonCircular(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
@Override
public void setPressed(boolean pressed) {
super.setPressed(pressed);
if (circlePaint != null) {
circlePaint.setColor(pressed ? pressedColor : defaultColor);
}
if (pressed) {
showPressedRing();
} else {
hidePressedRing();
}
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawCircle(centerX, centerY, pressedRingRadius + animationProgress, focusPaint);
canvas.drawCircle(centerX, centerY, outerRadius - pressedRingWidth, circlePaint);
super.onDraw(canvas);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
centerX = w / 2;
centerY = h / 2;
outerRadius = Math.min(w, h) / 2;
pressedRingRadius = outerRadius - pressedRingWidth - pressedRingWidth / 2;
}
public float getAnimationProgress() {
return animationProgress;
}
public void setAnimationProgress(float animationProgress) {
this.animationProgress = animationProgress;
this.invalidate();
}
public void setColor(int color) {
this.defaultColor = color;
this.pressedColor = getHighlightColor(color,PRESSED_COLOR_LIGHTUP);
circlePaint.setColor(defaultColor);
focusPaint.setColor(pressedColor);
focusPaint.setAlpha(PRESSED_RING_ALPHA);
this.invalidate();
}
/**Esconder anillo exterior animacion*/
private void hidePressedRing() {
pressedAnimator.setFloatValues(pressedRingWidth, 0f);
pressedAnimator.start();
}
public void PhidePressedRing() {
pressedAnimator.setFloatValues(pressedRingWidth, 0f);
pressedAnimator.start();
}
/**Mostrar anillo exterior animacion*/
private void showPressedRing() {
pressedAnimator.setFloatValues(animationProgress, pressedRingWidth);
pressedAnimator.start();
}
public void PshowPressedRing() {
pressedAnimator.setFloatValues(animationProgress, pressedRingWidth);
pressedAnimator.start();
}
private void init(Context context, AttributeSet attrs) {
this.setFocusable(true);
this.setScaleType(ScaleType.CENTER_INSIDE);
setClickable(true);
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setStyle(Paint.Style.FILL);
focusPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
focusPaint.setStyle(Paint.Style.STROKE);
pressedRingWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_PRESSED_RING_WIDTH_DIP, getResources()
.getDisplayMetrics());
//int color = Color.rgb(106, 142, 26);
/*if (attrs != null) {
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleButton);
color = a.getColor(R.styleable.CircleButton_cb_color, color);
pressedRingWidth = (int) a.getDimension(R.styleable.CircleButton_cb_pressedRingWidth, pressedRingWidth);
a.recycle();
}*/
int color = getResources().getColor(R.color.VerdeApp);
setColor(color);
focusPaint.setStrokeWidth(pressedRingWidth);
final int pressedAnimationTime = getResources().getInteger(ANIMATION_TIME_ID);
pressedAnimator = ObjectAnimator.ofFloat(this, "animationProgress", 0f, 0f);
pressedAnimator.setDuration(pressedAnimationTime);
}
private int getHighlightColor(int color, int amount) {
return Color.argb(Math.min(255, Color.alpha(color)), Math.min(255, Color.red(color) + amount),
Math.min(255, Color.green(color) + amount), Math.min(255, Color.blue(color) + amount));
}
}
package com.yottacode.pictogram.tabletlibrary.gui.communicator;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import com.yottacode.pictogram.dao.Picto;
import com.yottacode.pictogram.tabletlibrary.R;
import com.yottacode.pictogram.tabletlibrary.gui.communicator.cropper.EditPictoActivity;
import com.yottacode.pictogram.tabletlibrary.gui.login.MainActivity;
import com.yottacode.pictogram.tools.PCBcontext;
import com.yottacode.tools.GUITools;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
......@@ -80,7 +87,7 @@ public class PictoMenu {
activity.getIntent().putExtra(Picto.JSON_ATTTRS.EXPRESSION, expression);
//Enviar al PictogramActivity los datos necesarios para crear el picto despues
if (PCBcontext.getPcbdb().getCurrentUser().has_categories()) {
activity.getIntent().putExtra("cat", cat);
activity.getIntent().putExtra(Picto.JSON_ATTTRS.CATEGORY, cat);
activity.getIntent().putExtra(Picto.JSON_ATTTRS.ROW, row);
activity.getIntent().putExtra(Picto.JSON_ATTTRS.COLUMN, col);
} else {
......@@ -100,6 +107,44 @@ public class PictoMenu {
}
public void setPicto(int row, int col, int cat, String expression, Bitmap bitmap, int id_picto, String uri_sound, String user_avatar){
Intent intent = new Intent(activity, EditPictoActivity.class);
intent.putExtra(Picto.JSON_ATTTRS.EXPRESSION, expression);
intent.putExtra(Picto.JSON_ATTTRS.STUPICTO_ID,id_picto);
intent.putExtra(Picto.JSON_ATTTRS.URI_SOUND,uri_sound);
//Enviar al PictogramActivity los datos necesarios para editar el picto despues
if (PCBcontext.getPcbdb().getCurrentUser().has_categories()) {
intent.putExtra(Picto.JSON_ATTTRS.CATEGORY, cat);
intent.putExtra(Picto.JSON_ATTTRS.ROW, row);
intent.putExtra(Picto.JSON_ATTTRS.COLUMN, col);
} else {
intent.putExtra(Picto.JSON_ATTTRS.FREE_ROW, row);
intent.putExtra(Picto.JSON_ATTTRS.FREE_COLUMN, col);
}
if(bitmap!=null) {
Point size= GUITools.getScreenSize(activity);
float bWidth = bitmap.getWidth();
float bHeight = bitmap.getHeight();
float factorX=size.x*0.7f/bWidth;
float factorY=size.y*0.7f/bHeight;
float factor= factorY>factorX ? factorX : factorY;
bWidth=bWidth*factor;
bHeight=bHeight*factor;
Bitmap rescaled = Bitmap.createScaledBitmap(bitmap,(int) bWidth, (int) bHeight, true);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
rescaled.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
intent.putExtra(EditPictoActivity.IMAGE_PICTO, byteArray);
}
intent.putExtra("tipo",true);
activity.startActivityForResult(intent,EditPictoActivity.EDIT_PICTO_REQUEST);
}
/**Function for build a radial menu
*
* @param is_picto_big
......@@ -245,21 +290,29 @@ public class PictoMenu {
}
public String getName() { return "edit"; }
public String getLabel() { return null; }
public int getIcon() { return R.drawable.edit_picture; }
public int getIcon() { return R.drawable.edit; }
private List<RadialMenuWidget.RadialMenuEntry> children;
public List<RadialMenuWidget.RadialMenuEntry> getChildren() { return children; }
public void menuActiviated()
{
ll.getChildAt(1).setX(ll.getChildAt(1).getX() + 30);
children = new ArrayList<>(Arrays.asList(new PickFromCamera(p),new PickFromGallery(p)));
ll.setVisibility(View.GONE);
ll.removeAllViewsInLayout();
try {
setPicto(p.get_row(),p.get_column(),p.get_category(),p.get_translation(),p.get_bitmap(PCBcontext.getContext()),p.get_stupicto_id(),p.getUriSound(),p.getUserAvatar());
} catch (IOException e) {
e.printStackTrace();
}
//ll.getChildAt(1).setX(ll.getChildAt(1).getX() + 30);
//children = new ArrayList<>(Arrays.asList(new PickFromCamera(p),new PickFromGallery(p)));
}
public void menuDisabled(){
ll.getChildAt(1).setX(ll.getChildAt(1).getX() - 30);
//ll.getChildAt(1).setX(ll.getChildAt(1).getX() - 30);
}
}
public class PickFromCamera implements RadialMenuWidget.RadialMenuEntry
/*public class PickFromCamera implements RadialMenuWidget.RadialMenuEntry
{
Picto p;
public PickFromCamera(Picto picto){
......@@ -296,7 +349,7 @@ public class PictoMenu {
addPicto(p.get_row(),p.get_column(),p.get_category(),p.get_translation(),1);
}
public void menuDisabled(){}
}
}*/
public class newPickFromCamera implements RadialMenuWidget.RadialMenuEntry
{
......
......@@ -1127,8 +1127,6 @@ protected void showOnlyTape(boolean onlyTape) {
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
int cat = getIntent().getIntExtra("cat", -1);
Bitmap imagen = null;
switch(requestCode) {
case CAMERA_PIC_REQUEST: //Captura de foto
......@@ -1151,14 +1149,21 @@ protected void showOnlyTape(boolean onlyTape) {
break;
case EditPictoActivity.EDIT_PICTO_REQUEST:
if (resultCode == RESULT_OK) {
int row = getIntent().getIntExtra(Picto.JSON_ATTTRS.ROW, -1);
int col = getIntent().getIntExtra(Picto.JSON_ATTTRS.COLUMN, -1);
int freeRow = getIntent().getIntExtra(Picto.JSON_ATTTRS.FREE_ROW, -1);
int freeColumn = getIntent().getIntExtra(Picto.JSON_ATTTRS.FREE_COLUMN, -1);
boolean edit = data.getBooleanExtra("tipo",false);
int row = edit ? data.getExtras().getInt(Picto.JSON_ATTTRS.ROW) : getIntent().getIntExtra(Picto.JSON_ATTTRS.ROW, -1);
int col = edit ? data.getExtras().getInt(Picto.JSON_ATTTRS.COLUMN) : getIntent().getIntExtra(Picto.JSON_ATTTRS.COLUMN, -1);
int freeRow = edit ? data.getExtras().getInt(Picto.JSON_ATTTRS.FREE_ROW) : getIntent().getIntExtra(Picto.JSON_ATTTRS.FREE_ROW, -1);
int freeColumn = edit ? data.getExtras().getInt(Picto.JSON_ATTTRS.FREE_COLUMN) : getIntent().getIntExtra(Picto.JSON_ATTTRS.FREE_COLUMN, -1);
String uri_sound = edit ? data.getExtras().getString(Picto.JSON_ATTTRS.URI_SOUND) : getIntent().getStringExtra(Picto.JSON_ATTTRS.URI_SOUND);
int cat = edit ? data.getIntExtra(Picto.JSON_ATTTRS.CATEGORY, -1) : getIntent().getIntExtra(Picto.JSON_ATTTRS.CATEGORY, -1);
String path = data.getExtras().getString(EditPictoActivity.PATH);
String legend = data.getExtras().getString(Picto.JSON_ATTTRS.EXPRESSION);
chooseTextAndSavePicto(path, row, col, freeRow, freeColumn, cat, legend);
//TODO: COGER URI DEL SONIDO Y EL USER AVATAR
chooseTextAndSavePicto(path, row, col, freeRow, freeColumn, cat, legend, uri_sound, null);
refresh();
}
break;
}
......@@ -1169,7 +1174,7 @@ protected void showOnlyTape(boolean onlyTape) {
* función para la edición de un texto asociado a una nueva imagen y guardar el nuevo picto
*/
public void chooseTextAndSavePicto(final String selectedImagePath, final int row, final int col, final int freeRow, final int freeColumn,
final int category, final String legend) {
final int category, final String legend,final String uri_sound,final String user_avatar) {
// Set up the buttons
int cat = category != -1 ? category : Picto.NO_CATEGORY;
......@@ -1183,6 +1188,8 @@ protected void showOnlyTape(boolean onlyTape) {
col,
freeRow,
freeColumn,
uri_sound,
user_avatar,
new iLocalPicto() {
@Override
public void saved(Picto localPicto) {
......
......@@ -31,7 +31,7 @@ import com.yottacode.pictogram.tabletlibrary.gui.communicator.cropper.util.Paint
*
* Class to see it on the image to crop
*/
public class CropImageView extends ImageView {
public class CropImageView extends android.support.v7.widget.AppCompatImageView {
......
......@@ -22,7 +22,7 @@ public class PaintUtil {
final Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(resources.getDimension(R.dimen.border_thickness));
paint.setColor(resources.getColor(R.color.border));
paint.setColor(resources.getColor(R.color.VerdeApp));
return paint;
}
......@@ -35,7 +35,7 @@ public class PaintUtil {
final Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(resources.getDimension(R.dimen.guideline_thickness));
paint.setColor(resources.getColor(R.color.guideline));
paint.setColor(resources.getColor(R.color.VerdeApp));
return paint;
}
......@@ -62,7 +62,7 @@ public class PaintUtil {
final Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(resources.getDimension(R.dimen.corner_thickness));
paint.setColor(resources.getColor(R.color.corner));
paint.setColor(resources.getColor(R.color.VerdeApp));
return paint;
}
......
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- main color -->
<item
android:bottom="2dp"
android:left="2dp"
android:right="2dp">
<shape>
<solid android:color="#FFFFFF" />
</shape>
</item>
<item>
<selector >
<item android:state_enabled="true"
android:state_focused="true">
<shape>
<stroke
android:width="2dp"
android:color="@color/VerdeApp"/>
</shape>
</item>
<item android:state_enabled="true">
<shape>
<stroke
android:width="2dp"
android:color="#ffffffff"/>
</shape>
</item>
</selector>
</item>
<!-- draw another block to cut-off the left and right bars -->
<item android:bottom="5.0dp">
<shape>
<solid android:color="#ffffff" />
</shape>
</item>
</layer-list>
......@@ -37,7 +37,6 @@
<string name="session_eval_notevuated">not evaluated</string>
<string name="session_eval_discarded">discarded</string>
<string name="crop">Crop</string>
<string name="titleCropper">Edit Picto</string>
<string name="cancel">Cancel</string>
<string name="legendText">Legend</string>
......@@ -45,6 +44,8 @@
<!-- Cropper -->
<string name="crop_TextRequired">Por favor, introduzca una leyenda para el pictograma</string>
<string name="uploadingImage">Subiendo imagen al servidor</string>
<string name="titleCropperEdit">Edit Picto</string>
<string name="titleCropperNew">New Picto</string>
</resources>
......@@ -37,14 +37,14 @@
<string name="session_eval_notevuated">no evaluado</string>
<string name="session_eval_discarded">inválido</string>
<string name="crop">Recortar</string>
<string name="titleCropper">Nuevo Pictograma</string>
<string name="crop_TextRequired">Por favor, introduzca una leyenda para el pictograma</string>
<!-- Cropper -->
<string name="legendText">Leyenda:</string>
<string name="uploadingImage">Subiendo imagen al servidor</string>
<string name="cancel">Cancelar</string>
<string name="titleCropperEdit">Editar Pictograma</string>
<string name="titleCropperNew">Nuevo Pictograma</string>
</resources>
......@@ -42,8 +42,9 @@
<string name="legendText">Leyenda:</string>
<string name="crop">Recortar</string>
<string name="titleCropper">Nuevo Pictograma</string>
<string name="titleCropperNew">Nuevo Pictograma</string>
<string name="titleCropperEdit">Editar Pictograma</string>
<string name="crop_TextRequired">Por favor, introduzca una leyenda para el pictograma</string>
<string name="uploadingImage">Subiendo imagen al servidor</string>
<string name="cancel">Cancel</string>
</resources>
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":tabletlibrary" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" version="4">
<module external.linked.project.id=":tabletlibrary" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
......
......@@ -53,3 +53,6 @@ else
echo "XX Playbook not found, provision not finished"
exit
fi
# overwrite sails-mysql
yes | sudo cp -rf /vagrant/src/node_modules_overwrite/sails-mysql/* /vagrant/src/node_modules/sails-mysql/
......@@ -7,20 +7,27 @@
cd /vagrant/
echo "--Descargando coleccion de pictogramas"
wget http://dev.yottacode.com/symbolstx.tgz.gpg
wget http://dev.yottacode.com/upload.tgz.gpg
wget https://dev.pictogramweb.com/symbolstx.tgz.gpg
wget https://dev.pictogramweb.com/upload.tgz.gpg
wget https://dev.pictogramweb.com/arasaac.tgz.gpg
echo "--Desencriptando coleccion"
echo r\"YjtnB+a4$.M*nJ | gpg --batch --no-tty --yes --passphrase-fd 0 symbolstx.tgz.gpg
echo r\"YjtnB+a4$.M*nJ | gpg --batch --no-tty --yes --passphrase-fd 0 upload.tgz.gpg
echo r\"YjtnB+a4$.M*nJ | gpg --batch --no-tty --yes --passphrase-fd 0 arasaac.tgz.gpg
echo "--Descomprimiendo coleccion"
tar zxvf /vagrant/symbolstx.tgz
tar zxvf /vagrant/upload.tgz
tar zxvf /vagrant/arasaac.tgz
echo "--Renombrado y borrado de archivos"
rm upload.tgz
rm upload.tgz.gpg
rm symbolstx.tgz
rm symbolstx.tgz.gpg
mv symbolstx_96x82 symbolstx
rm arasaac.tgz
rm arasaac.tgz.gpg
This diff could not be displayed because it is too large.
......@@ -55,9 +55,8 @@ INSERT INTO `meta_instruction` (`id` ,`name` ,`objective` ,`id_met`, `lang`) VA
INSERT INTO `source` (`id`, `name`, `description`) VALUES
(1, 'SymbolStix', 'n2y SymbolStix pictograms collection'),
(2, 'Custom', 'Uploaded pictograms by a given user');
;
(2, 'Custom', 'Uploaded pictograms by a given user'),
(3, 'Arasaac', 'Arasaac pictograms collection');
--
-- Volcado de datos para la tabla `picto`
......
......@@ -372,6 +372,8 @@ CREATE TABLE IF NOT EXISTS `supervisor` (
`password` varchar(60) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT 'Encrypted password using the BCrypt algorithm',
`id_off` int(11) DEFAULT NULL,
`active` boolean DEFAULT FALSE,
`arasaac_license` boolean DEFAULT FALSE,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
KEY `id_off` (`id_off`)
......
......@@ -24,6 +24,15 @@
state: import
target: "{{ server_path }}/{{ database_files_relative_path }}/symbolstix.sql"
- name: Imports arasaac pictos
mysql_db:
login_user: "{{ database_user }}"
login_password: "{{ database_user_passwd }}"
name: "{{ database_name }}"
state: import
target: "{{ server_path }}/{{ database_files_relative_path }}/arasaac.sql"
- name: Imports application essential data
mysql_db:
login_user: "{{ database_user }}"
......
......@@ -4,7 +4,7 @@ Changes to be performed manually in servers to upgrade
## AngularJS
(already done in dev)
(already done in dev & pre)
- angular-re-captcha has been replaced by angular-recaptcha, so bower has to be run
- reinstall ui-bootstrap
......@@ -15,6 +15,13 @@ Changes to be performed manually in servers to upgrade
(already done in dev)
- add arasaac to source table
`INSERT INTO `source` (`id`, `name`, `description`) VALUES (3, 'Arasaac', 'Arasaac pictograms collection');`
- alter table supervisor add arasaac license:
`ALTER TABLE supervisor ADD COLUMN arasaac_license BOOLEAN DEFAULT FALSE;`
(already done in dev & pre)
- load pictocat_tree_populate.sql
`source /vagrant/roles/database/files/pictocat_tree_populate.sql;`
- reload trigers-enrolments-integrity-constraints.sql
......
......@@ -372,6 +372,70 @@ module.exports = {
},
/**
* Return all pictos from Arasaac using the language of the specified supervisor.
* @param {request} req {} (with supervisorId as url parameters)
* @param {response} res
* [
* {
* expressions: [
* // There should be just one expression per picto
* // with the language being used by the supervisor
* {
* id: 1234,
* lang: 'es-es',
* text: 'nacimiento',
* picto: 23
* }
* ],
* source: 1,
* owner: null,
* id: 23,
* uri: 'picto/uri.jpg',
* category: 41
* }
* ]
*/
fromArasaac: function (req, res) {
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();
}
})
.catch(() => res.serverError());
},
/**
* Add a tag to an existing picto. This tag is associated to the supervisor.
* @param {request} req
* {
......
......@@ -95,24 +95,42 @@ module.exports = {
* @param {request} req {} (with studentId specified as url parameters)
* @param {response} res
* {
* id: 12,
* office: 1234,
* username: 'johnydoe',
* name: 'Johny',
* surname: 'Doe',
* birthdate: '2009-12-10T00:00:00.000Z',
* gender: 'F',
* country: 'ES',
* pic: 'avatar/nice/url.jpg',
* notes: null,
* lang: 'en-en',
* iat: 123512,
* exp: 1231292,
* attributes: { @see Student.getValidAttributes() },
* current_method: 'Do Things', // May be null
* current_instruction: 'Do Stuff', // May be null
* supervision: 0|1|2, // supervision level according to requester 0 -> office admin, 1 -> tutor, 2 -> therapist
* }
"office": 383,
"id": 92,
"username": "jose",
"name": "AAjose",
"surname": "AAjose antonio",
"birthdate": "2009-05-12T00:00:00.000Z",
"gender": "M",
"country": "ES",
"pic": "/upload/studentAvatar/defaultAvatar.jpg",
"notes": "",
"lang": "es-es",
"current_method": "Comunicación Aumentativa y Adaptativa", // May be "no method"
"current_instruction": "Fase 4 - Estructura de la oración", // May be "no instruction"
"supervision": 2 // supervision level according to requester 0 -> office admin, 1 -> tutor, 2 -> therapist, 3 -> student himself
"attributes": { @see Student.getValidAttributes()
"categories": true,
"input_feedback": {
"vibration": true,
"read": false,
"beep": false,
"highlight": false
},
"input_selection": {
"click": true,
"double_click": false,
"long_press": false,
"drag": true
},
"legend": false,
"legend_size": "normal",
"size": "large",
"picto_background": "#0000ff",
"tape_background": "#00ffff",
"delivery": 0
}
}
*/
getInfo: function (req, res) {
Student.findOne({id: req.params.id_stu})
......@@ -144,9 +162,9 @@ module.exports = {
else if (stu_sup && !req.token.office)
student.supervision = 1; // requester is tutor of the studend
else if (stu_sup && req.token.office && student.office == req.token.office.id)
student.supervision = 2; // requester is supervisor of student
else if (req.token.isStudent && req.token.id == student.id)
student.supervision = 3 // requester is the student himself
student.supervision = 2; // requester is supervisor of student
else if (req.token.isStudent && req.token.id == student.id)
student.supervision = 3 // requester is the student himself
if (student.supervision == -1) // should not hace access!!!
return res.forbidden("Access to this student should not be granted to you");
......@@ -966,7 +984,9 @@ module.exports = {
* legend: true/[false],
* legend_size: '[small]/large',
* expression: 'custom expression',
* color: any valid HEX color or [null]
* color: any valid HEX color or [null],
* sound_uri: path to sound file,
* user_avatar: email (supervisor) or username (student) for associated account
* }
* },
* }
......
......@@ -200,6 +200,32 @@ module.exports = {
},
/**
* Acept Arasaac License
* @param {request} req
* {
* "token": "12398123aas78sf798as7d987234" // Encryted code with supervisor ID, siging role and id_off
* }
*/
accept_arasaac: function (req, res) {
var params = req.params.all();
Supervisor.findOne(params.id)
.then(function (supervisor) {
if (!supervisor)
throw new Error("Error when looking for user");
supervisor.arasaacLicense = true;
delete supervisor.password;
supervisor.save();
res.ok();
})
.catch(function (err) {
return res.serverError(err.message ? err.message : 'Supervisor not found');
});
},
/**
* Gets a supervisor by his email
* @param {request} req {} (width email as url parameter)
* @param {response} res
......@@ -261,7 +287,7 @@ module.exports = {
create: function (req, res) {
var params = req.params.all();
var supervisor;
// Send email confirmation
function sendConfirmationMail(cb) {
......@@ -318,7 +344,7 @@ module.exports = {
return res.serverError("Supervisor created but returned null");
supervisor = sup;
if (params.role === 'therapist_office' || params.role === 'tutor_office') {
sendConfirmationMail((err) => {
if (err) throw err;
......
......@@ -90,6 +90,8 @@ module.exports = {
color: null,
expression: null,
legend: 'none',
uri_sound: null,
user_avatar: null
};
if (typeof attributes === 'object') {
......@@ -128,13 +130,19 @@ module.exports = {
}
if (!((/^(none|normal|full)$/).test(validAttributes.legend))) {
delete validAttributes.legend;
}
}
if (typeof validAttributes.highlight !== 'boolean') {
delete validAttributes.highlight;
}
if (!((/^#([0-9a-f]{3}){1,2}$/i).test(validAttributes.color))) {
delete validAttributes.color;
}
if (typeof validAttributes.sound_uri!== 'string') {
delete validAttributes.sound_uri;
}
if (typeof validAttributes.user_avatar !== 'string') {
delete validAttributes.user_avatar;
}
}
sails.log.verbose('Valid attributes for StuPicto', validAttributes);
return Object.assign({}, defaultAttributes, validAttributes);
......
......@@ -84,6 +84,10 @@ module.exports = {
active: {
type: 'boolean'
},
arasaacLicense: {
type: 'boolean',
columnName: 'arasaac_license'
},
office: {
columnName: 'id_off',
type: 'integer',
......
......@@ -30,6 +30,8 @@
"apply":"Apply",
"annual": "Annual",
"April": "April",
"arasaac_license": "Los símbolos pictográficos utilizados en esta sección son propiedad de CATEDU (http://arasaac.org/) bajo licencia Creative Commons y han sido creados por Sergio Palao.",
"arasaac_license_import": "The pictographic symbols used in this section are the property of CATEDU (http://arasaac.org/) under a Creative Commons license and have been created by Sergio Palau. To use them you must accept the license of use by clicking on the button import.",
"attributes_not_updated": "Changes not saved",
"attributes_updated": "Changes saved",
"attributes_updating": "Saving...",
......@@ -111,6 +113,7 @@
"enlarge": "Enlarge",
"enormous": "Enormous",
"error_adding_picto": "Error adding picto",
"error_arasaac_license": "Error accepting Arasaac license",
"error_creating_session": "Error when creating session",
"error_deleting_picto": "Error deleting picto",
"error_downloading_supervisors": "Error downloading supervisors",
......@@ -145,6 +148,7 @@
"highlighted": "Highlighted",
"hours": "hours",
"how_many": "How many?",
"import": "Import",
"inactive_account": "This account has not been activated. Please, follow the link sent to your email address.",
"input_selection": "How to place a pictogram",
"instruction": "Instruction",
......
......@@ -30,6 +30,8 @@
"apply":"Aplicar",
"annual": "Anual",
"April": "Abril",
"arasaac_license": "Los símbolos pictográficos utilizados en esta sección son propiedad de CATEDU (http://arasaac.org/) bajo licencia Creative Commons y han sido creados por Sergio Palao.",
"arasaac_license_import": "Los símbolos pictográficos utilizados en esta sección son propiedad de CATEDU (http://arasaac.org/) bajo licencia Creative Commons y han sido creados por Sergio Palao. Para usarlos deberá aceptar la licencia de uso haciendo clic sobre el botón importar.",
"attributes_not_updated": "Cambios no guardados",
"attributes_updated": "Cambios guardados",
"attributes_updating": "Guardando...",
......@@ -114,6 +116,7 @@
"expand_navigation": "Desplegar navegación",
"expression": "Expresión",
"error_adding_picto": "Error al añadir el picto",
"error_arasaac_license": "Error al aceptar la licencia de Arasaac",
"error_creating_session": "Error al crear sesión",
"error_deleting_picto": "Error borrando el picto",
"error_downloading_supervisors": "Error al descargar los supervisores",
......@@ -145,6 +148,7 @@
"highlighted": "Resaltado",
"hours": "horas",
"how_many": "¿Cuántas?",
"import": "Importar",
"inactive_account": "Esta cuenta no ha sido activada. Por favor, siga el enlace de confirmación enviado a su dirección de correo electrónico.",
"input_selection": "Cómo colocar un pictograma",
"instruction": "Instrucción",
......
/vagrant/arasaac
\ No newline at end of file
......@@ -242,12 +242,10 @@ dashboardDirectives.directive('popoveraddpicto', function() {
restrict: 'A',
link: function (scope, element, attrs) {
if(element[0].y <= y){
y=element[0].y;
attrs.popoverPlacement="bottom";
}
console.log(element[0].y);
console.log(angular.element( document.querySelector( '#collections' ) ));
if(element[0].y <= y){
y=element[0].y;
attrs.popoverPlacement="bottom";
}
}
}
});
<!-- Office image -->
<div class="row">
<div class="col-md-12 text-center">
<!-- Logo Pictogram
<p>
<img src="img/logo_pictogram.png" alt="Pictogram" title="Pictogram" />
</p>
-->
<p>&nbsp;</p>
<p class="text-center">
<div class="header-image">
<div class="row">
<div class="col-md-12 text-center">
<img ng-src="{{office.logoUrl}}" alt="{{office.name}}" title="{{office.name}}">
</p>
</div>
</div>
</div>
<!--/. Office image -->
<!-- Main row -->
<div class="row">
<br>
<!-- Form column and offset -->
<div class="col-md-4 col-md-offset-2">
<div id="login">
<!-- Formulario -->
<!-- LoginCtrl controls here, see app.js -->
<form name="loginForm" ng-submit="login()" novalidate>
<!-- Email -->
<div class="form-group">
<label translate>email</label>:
<input type="email" class="form-control" id="login_email" placeholder="{{ 'your_email' | translate}}" required ng-model="credentials.email" />
</div>
<!-- Password -->
<div class="form-group">
<label translate>password</label>:
<input type="password" class="form-control" id="login_password" placeholder="{{ 'your_password' | translate}}" required ng-model="credentials.password" />
</div>
<!-- Remember -->
<div class="checkbox">
<label>
<input type="checkbox" id="login_savepassword" ng-model="credentials.savepassword" />{{ 'remember' | translate }}
</label>
</div>
<div class="row">
<div class="col-md-12">
<!-- Login -->
<div class="pull-left">
<button type="submit" class="btn btn-primary" translate>login</button>
</div>
<!-- Spinner -->
<div class="pull-left">
<i ng-class="{'fa fa-spinner fa-spin fa-2x fa-fw margin-bottom': true, 'spin_disabled': !submitted}"></i>
<div id="main-content" class="container">
<div class="row">
<!-- Form column and offset -->
<div class="col-md-4 col-md-offset-2">
<div id="login">
<!-- Formulario -->
<!-- LoginCtrl controls here, see app.js -->
<form name="loginForm" ng-submit="login()" novalidate>
<!-- Email -->
<div class="form-group">
<label translate>email</label>:
<input type="email" class="form-control" id="login_email" placeholder="{{ 'your_email' | translate}}" required ng-model="credentials.email" />
</div>
<!-- Password -->
<div class="form-group">
<label translate>password</label>:
<input type="password" class="form-control" id="login_password" placeholder="{{ 'your_password' | translate}}" required ng-model="credentials.password" />
</div>
<div class="row">
<div class="col-xs-6">
<!-- Login -->
<div class="pull-left">
<button type="submit" class="btn btn-primary" translate>login</button>
</div>
<!-- Spinner -->
<div class="pull-left">
<i ng-class="{'fa fa-spinner fa-spin fa-2x fa-fw margin-bottom': true, 'spin_disabled': !submitted}"></i>
</div>
</div>
<!-- Create account -->
<div class="pull-right margin-top7">
<a href="/app/#/signin" translate>create_an_account</a>
<div class="col-xs-6 margin-top7">
<!-- Remember -->
<div class="checkbox">
<label>
<input type="checkbox" id="login_savepassword" ng-model="credentials.savepassword" />{{ 'remember' | translate }}
</label>
</div>
</div>
</div>
</div>
<!-- Remember password -->
<div class="text-center margin-top15">
<br>
<a href="/app/#/changepass" translate>password_forgotten</a>
</div>
</form>
<!-- Remember password -->
<div class="row text-center">
<a href="/app/#/changepass" translate>password_forgotten</a>
</div>
<!-- Create account -->
<div class="row text-center">
<a href="/app/#/signin" translate>create_an_account</a>
</div>
</form>
</div>
<!--/. login -->
</div>
<!--/. login -->
</div>
<!--/. form column -->
<!--/. form column -->
<!-- Image column -->
<div class="col-md-4">
<img src="img/login.png" alt="Pictogram" title="Pictogram" />
</div>
<!--/. image column -->
<!-- Image column -->
<div class="col-xs-12 col-md-4 text-center">
<img src="img/login.png" alt="Pictogram" title="Pictogram" />
</div>
<!--/. image column -->
</div>
</div>
<!--/. main row -->
<footer-translate></footer-translate>
......@@ -29,6 +29,7 @@ dashboardControllers.controller('AddPictoCtrl', function (
$scope.loadingCatPictos = false;
$scope.radioModel = 'Middle';
$scope.onlyOwn = onlyOwn;
$scope.showArasaacLicense = !supervisor.arasaacLicense; //If true, won't show license agreement
/*
* Get data about SymbolStix
......@@ -72,6 +73,49 @@ dashboardControllers.controller('AddPictoCtrl', function (
});
};
$scope.accept_arasaac = function (){
$http.get(config.backend + '/sup/arasaac_license/' + supervisor.id)
.success(function () {
$scope.showArasaacLicense = false;
supervisor.arasaacLicense = true;
$scope.load_arasaac_pictos();
})
.error(function () {
$translate('error_arasaac_license').then(function (translation) {
ngToast.danger({ content: translation });
});
});
};
$scope.load_arasaac_pictos = function () {
$scope.pictos = [];
$scope.page = 1;
if(!$scope.showArasaacLicense){
$scope.loadingCatPictos = true;
var request = "";
//Request page X from all pictos (symbolstx)
request = config.backend + '/sup/' + supervisor.id +
'/pic_fromArasaac/page/'+$scope.page+'/limit/'+$scope.limit;
$http.get(request)
.success(function (data) {
if (data && $scope.source == 'arasaac'){
$scope.pictos = data;
}
$scope.loadingCatPictos = false;
setTimeout(function () { $scope.$apply(); });
})
.error(function () {
$translate('error_loading_pictos').then(function (translation) {
ngToast.danger({ content: translation });
});
$scope.loadingCatPictos = false;
});
}
};
//
// Load pictos owned by the actual supervisor
//
......@@ -288,16 +332,22 @@ dashboardControllers.controller('AddPictoCtrl', function (
$scope.page += 1;
var request = "";
if($scope.breadcrumbs.length == 1) {
if($scope.source == "symbolstx"){
if($scope.breadcrumbs.length == 1) {
//Request page X from all pictos (symbolstx)
request = config.backend + '/sup/' + supervisor.id +
'/pic_fromSymbolStx/page/'+$scope.page+'/limit/'+$scope.limit;
}else{
request = config.backend + '/sup/' + supervisor.id +
'/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 +
'/pic_fromSymbolStx/page/'+$scope.page+'/limit/'+$scope.limit;
}else{
request = config.backend + '/sup/' + supervisor.id +
'/pic_fromCatSubcat/category/'+$scope.breadcrumbs[$scope.breadcrumbs.length-1].id
+'/page/'+$scope.page+'/limit/'+$scope.limit;
'/pic_fromArasaac/page/'+$scope.page+'/limit/'+$scope.limit;
}
$http.get(request)
.success(function (data) {
$scope.pictos = $scope.pictos.concat(data);
......@@ -324,17 +374,19 @@ dashboardControllers.controller('AddPictoCtrl', function (
}else if(length == 0){ // If there is no word, reset pictos
if ($scope.onlyOwn || $scope.source == "ownpictos"){
$scope.load_own_pictos();
}else{
}else if($scope.source == "symbolstx"){
$scope.open_category_from_bc(0);
}else if($scope.source == "arasaac"){
$scope.load_arasaac_pictos();
}
}else{
var request = "";
var source = 1;
var source = 1; //symbolstx
$scope.closeAlert();
$scope.loadingCatPictos = true;
//category to look in
var category;
var category = 0; //All pictos
if (!$scope.onlyOwn){
category = $scope.breadcrumbs[$scope.breadcrumbs.length-1].id;
if(category == 999){
......@@ -344,7 +396,8 @@ dashboardControllers.controller('AddPictoCtrl', function (
if($scope.source == "ownpictos"){
source = 2;
category = 0;
}else if($scope.source == "arasaac"){
source = 3;
}
request = config.backend + '/sup/' + supervisor.id +
'/pic_fromSearch/'+$scope.srch_term_picto+'/category/'+category+
......@@ -352,7 +405,7 @@ dashboardControllers.controller('AddPictoCtrl', function (
// Add Search to breadcrumbs
if (!$scope.onlyOwn){
if($scope.breadcrumbs[$scope.breadcrumbs.length-1].id != 999){
if($scope.breadcrumbs[$scope.breadcrumbs.length-1].id != 999 && $scope.source == "symbolstx"){
$scope.breadcrumbs.push({
id: 999,
exp: "filter",
......
......@@ -330,7 +330,6 @@ dashboardControllers.controller('StudentCollectionsCtrl', function StudentCollec
new_id_pic: pictoId
})
.success(function (studentPicto) {
console.log(JSON.stringify(studentPicto));
$scope.loadPictos();
// notify
......@@ -352,7 +351,6 @@ dashboardControllers.controller('StudentCollectionsCtrl', function StudentCollec
// Adds a new pictogram
//
$scope.open_add = function (col, row) {
console.log(col + " " +row);
var modalInstance = $modal.open({
animation: true,
templateUrl: 'modules/student/views/addpicto.html',
......@@ -389,7 +387,6 @@ dashboardControllers.controller('StudentCollectionsCtrl', function StudentCollec
}
})
.success(function (studentPicto) {
console.log(studentPicto);
placePicto(studentPicto);
io.socket.post('/stu/vocabulary', {
......
......@@ -117,14 +117,14 @@ dashboardControllers.controller('StudentReportsCtrl', function StudentReportsCtr
"broken":0, "null":0
};
$scope.method_chart_dates = []; // [2010-02....]
$scope.error_rate_rate = []; // [33.3, ...]
$scope.average_time_trie = []; // [3, 4,...] seconds
$scope.average_time_pictos = [];
$scope.vocab_size = [];
$scope.method_chart_dates=[[]];
$scope.error_rate_rate = [[]];
$scope.average_time_trie = [[]];
$scope.average_time_pictos = [[]];
$scope.vocab_size = [[]];
$scope.vocab_size_aux = [];
$scope.phrase_average_time= [];
$scope.phrase_average_size = [];
$scope.phrase_average_time = [[]];
$scope.phrase_average_size = [[]];
if(selected_method.class === "method-opt"){
//check the selected method
......@@ -139,29 +139,13 @@ dashboardControllers.controller('StudentReportsCtrl', function StudentReportsCtr
}
//There is a method selected
//Get the selected method/s instructions by date
$scope.method_chart_dates=[[]];
$scope.error_rate_rate = [[]];
$scope.average_time_trie = [[]];
$scope.average_time_pictos = [[]];
$scope.vocab_size = [[]];
$scope.phrase_average_time = [[]];
$scope.phrase_average_size = [[]];
for(var i=0; i < $scope.statistic_methods.length; i++){
for(var j=0; j < $scope.statistic_methods[i].instructions.length; j++){
if(new Date($scope.statistic_methods[i].instructions[j].begin).getTime() > $scope.reportDateSince.getTime()
&& new Date($scope.statistic_methods[i].instructions[j].begin).getTime() < $scope.reportDateTo.getTime()){
//llamar a la funcion estadisticas con esta instruccion
var statistics = statistics_instruction(j, i);
$scope.error_rate_rate[0].push(statistics[7]);
$scope.average_time_trie[0].push(statistics[8]);
$scope.average_time_pictos[0].push(statistics[9]);
$scope.vocab_size[0].push(statistics[10]);
$scope.phrase_average_time[0].push(statistics[11]);
$scope.phrase_average_size[0].push(statistics[12]);
$scope.method_chart_dates[0].push(moment($scope.statistic_methods[i].instructions[j].begin).format("YYYY-MM-DD"));
// $scope.error_rate_rate[0].push(statistics_instruction(j, i)[2].error_rate);
// $scope.error_rate_dates[0].push(moment($scope.statistic_methods[i].instructions[j].begin).format("YYYY-MM-DD"));
}
}
}
......@@ -184,14 +168,6 @@ dashboardControllers.controller('StudentReportsCtrl', function StudentReportsCtr
if(new Date($scope.statistic_methods[0].instructions[j].begin).getTime() > $scope.reportDateSince.getTime()
&& new Date($scope.statistic_methods[0].instructions[j].begin).getTime() < $scope.reportDateTo.getTime()){
var statistics = statistics_instruction(j, 0);
$scope.error_rate_rate.push(statistics[1]);
$scope.method_chart_dates.push(statistics[0]);
$scope.average_time_trie.push(statistics[2]);
$scope.average_time_pictos.push(statistics[3]);
$scope.vocab_size.push(statistics[4]);
$scope.phrase_average_time.push(statistics[5]);
$scope.phrase_average_size.push(statistics[6]);
}
}
}
......@@ -359,24 +335,8 @@ dashboardControllers.controller('StudentReportsCtrl', function StudentReportsCtr
* Instruction selected
* method_pos is the position of the method in $scope.statistic_methods
* instruction_pos is the position of the instruction in $scope.statistic_methods
* return instruction_statistic [
[tries dates],
[tries error rate],
[tries average time],
[average_time_between_pictos_ws],
[vocab_size_ws],
[phrase_average_build_time],
[phrase_average_size],
[instruction error_rate],
[instruction tries average time],
[instruction average_time_between_pictos],
[instruction_vocab_size],
[instruction_phrase_average_build_time],
[instruction_phrase_average_size]
]
*/
function statistics_instruction(instruction_pos, method_pos){
var instruction_statistic = [[],[], [],[],[],[],[], 0, 0, 0, 0,0,0];
var working_sessions=[];
//Get the selected instruction's working sessions by date
......@@ -389,9 +349,6 @@ dashboardControllers.controller('StudentReportsCtrl', function StudentReportsCtr
}
}
var instruction_error_rate = 0;
var instruction_tries_average_time = 0;
var instruction_pictos_average_time = 0;
var instruction_phrase_average_size = 0;
var instruction_phrase_average_build_time = 0;
for(var i=0; i < working_sessions.length; i++){
......@@ -438,7 +395,6 @@ dashboardControllers.controller('StudentReportsCtrl', function StudentReportsCtr
if(working_sessions[i].tries[j].actions.length > 0){
var average_time_pictos_action = 0;
var phrase_average_size_action = 0;
var before = moment(new Date(working_sessions[i].tries[j].actions[0].timestamp),"DD/MM/YYYY HH:mm:ss");
for(var k = 1; k < working_sessions[i].tries[j].actions.length; k++){
......@@ -468,42 +424,27 @@ dashboardControllers.controller('StudentReportsCtrl', function StudentReportsCtr
miliseconds = moment.duration(dif).asMilliseconds();
phrase_average_build_time += miliseconds;
}
phrase_average_size += count_pictos;
}
}
average_time_pictos_ws += average_time_pictos_action / working_sessions[i].tries[j].actions.length;
}
}
$scope.tries_count["total"]+=working_sessions[i].tries.length;
error_rate = success / working_sessions[i].tries.length;
instruction_error_rate += error_rate;
tries_average_time = tries_average_time / working_sessions[i].tries.length; //average time per trie per ws
instruction_tries_average_time += tries_average_time;
average_time_pictos_ws = average_time_pictos_ws / working_sessions[i].tries.length;
instruction_pictos_average_time += average_time_pictos_ws;
phrase_average_build_time = phrase_average_build_time / working_sessions[i].tries.length; //milliseconds
instruction_phrase_average_build_time += phrase_average_build_time; //milliseconds
phrase_average_size = phrase_average_size / working_sessions[i].tries.length;
instruction_phrase_average_size += phrase_average_size;
instruction_statistic[0].push(moment(working_sessions[i].begin).format("YYYY-MM-DD")); //https://github.com/moment/moment/issues/1407
instruction_statistic[1].push(round((1-error_rate) * 100, 2));
instruction_statistic[2].push(round(moment.duration(tries_average_time).asSeconds(),2));
instruction_statistic[3].push(round(moment.duration(average_time_pictos_ws).asSeconds(), 2));
instruction_statistic[4].push($scope.vocab_size_aux.length);
instruction_statistic[5].push(round(moment.duration(phrase_average_build_time).asSeconds(),2));
instruction_statistic[6].push(phrase_average_size);
phrase_average_build_time = phrase_average_build_time / success; //milliseconds
phrase_average_size = phrase_average_size / success;
$scope.method_chart_dates[0].push(moment(working_sessions[i].begin).format("YYYY-MM-DD")); //https://github.com/moment/moment/issues/1407
$scope.error_rate_rate[0].push(round((1-error_rate) * 100, 2));
$scope.average_time_trie[0].push(round(moment.duration(tries_average_time).asSeconds(),2));
$scope.average_time_pictos[0].push(round(moment.duration(average_time_pictos_ws).asSeconds(), 2));
$scope.vocab_size[0].push($scope.vocab_size_aux.length);
$scope.phrase_average_time[0].push(round(moment.duration(phrase_average_build_time).asSeconds(),2));
$scope.phrase_average_size[0].push(phrase_average_size);
}
instruction_statistic[7] = round(((1 - instruction_error_rate) / working_sessions.length) * 100, 2);
instruction_statistic[8] = round(moment.duration(instruction_tries_average_time / working_sessions.length ).asSeconds() , 2);
instruction_statistic[9] = round(moment.duration(instruction_pictos_average_time / working_sessions.length ).asSeconds(), 2);
instruction_statistic[10] = $scope.vocab_size_aux.length;
instruction_statistic[11] = round(moment.duration(instruction_phrase_average_build_time / working_sessions.length ).asSeconds(), 2);
instruction_statistic[12] = round(instruction_phrase_average_size / working_sessions.length, 2);
return instruction_statistic;
}
function round(number, places) {
......
......@@ -21,6 +21,9 @@
<button class="btn btn-default" btn-radio="'symbolstx'" ng-model="source" ng-click="open_category_from_bc('0')">
<span class="glyphicon glyphicon-th"></span> SymbolStix
</button>
<button class="btn btn-default" btn-radio="'arasaac'" ng-model="source" ng-click="load_arasaac_pictos()">
<i class="fa fa-th" aria-hidden="true"></i> ARASAAC
</button>
<button class="btn btn-default" btn-radio="'ownpictos'" ng-model="source" ng-click="load_own_pictos()">
<span class="glyphicon glyphicon-picture"></span> {{ 'own_pictos' | translate }}
</button>
......@@ -72,6 +75,17 @@
<!-- Collections row -->
<div class="row">
<div id="arasaac_agreement" class="col-md-12" ng-show="showArasaacLicense && source == 'arasaac'">
<div class="panel panel-warning">
<div class="panel-heading">
<h3 class="panel-title"> ARASAAC</h3>
</div>
<div class="panel-body">
<h3><small>{{'arasaac_license_import' | translate}}</small></h3>
<button class="btn btn-primary" ng-click="accept_arasaac()">{{'import' | translate}}</button>
</div>
</div>
</div>
<!-- Collections -->
<div id="collections" class="col-md-12 category-collection"
......@@ -105,6 +119,9 @@
</div><!-- /modal-body -->
<div class="modal-footer">
<div class="arasaac_license" ng-show="source == 'arasaac'">
<p><small>{{'arasaac_license' | translate}}</small></p>
</div>
<button class="btn btn-success pull-left" ng-show="source == 'ownpictos'" ngf-select ng-model="picFile" accept="image/*" ngf-change="addOwnPicto()">
<i class="fa fa-folder-open" aria-hidden="true"></i> {{ 'new_img' | translate }}
</button>
......
......@@ -33,6 +33,7 @@ dashboardControllers.controller('SupervisorCtrl', function SupervisorCtrl(
$scope.user.lang = user.lang;
$scope.user.isSupAdmin = user.isSupAdmin;
$scope.user.isTutor = user.isTutor;
$scope.user.arasaacLicense = user.arasaacLicense;
// Link to setup
$scope.setup = function(){
......
......@@ -12,6 +12,15 @@ dashboardControllers.controller('TranslateController', function(
ngToast,
vcRecaptchaService
) {
// onload, set lang accordingly to stored user settings
if ($window.sessionStorage.user) {
//Session variables update
var obj = JSON.parse($window.sessionStorage.user);
$translate.use(obj.lang);
}
// Changes the language when user click on footer lang
$scope.changeLanguage = function (langKey) {
//Translate update
......@@ -41,7 +50,11 @@ dashboardControllers.controller('TranslateController', function(
}
// Reload captcha according to language (only once instance per page, so id is always 0)
vcRecaptchaService.useLang(0, langKey.substr(0,2)); //TODO: REVISAR reCaptcha Widget ID not exists
try {
vcRecaptchaService.useLang(0, langKey.substr(0,2));
} catch (err) {}
// Reload page
$window.location.reload();
};
});
......@@ -1023,6 +1023,10 @@ form .progress {
.method-opt{
font-weight: 600;
}
.arasaac_license{
text-align: left;
color: #6c6c6c;
}
.header-image {
width: 100%;
......
......@@ -75,6 +75,7 @@ module.exports.policies = {
categories: ['tokenAuth'],
fromcategory: ['tokenAuth'],
fromSymbolStx: ['tokenAuth'],
fromArasaac: ['tokenAuth'],
fromCatSubcat: ['tokenAuth'],
fromSearch: ['tokenAuth']
},
......@@ -134,6 +135,7 @@ module.exports.policies = {
change_password: true,
request_change_password: true,
activate: true,
accept_arasaac: ['tokenAuth'],
upload: ['tokenAuth'],
subscribe: ['tokenAuth'],
unsubscribe: ['tokenAuth'],
......
......@@ -107,10 +107,12 @@ module.exports.routes = {
'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',
'PUT /sup/changepass': 'SupervisorController.change_password',
'PUT /sup/:id': 'SupervisorController.update',
'POST /sup': 'SupervisorController.create',
......
......@@ -499,7 +499,7 @@ function toSqlDate(date) {
('00' + date.getDate()).slice(-2) + ' ' +
('00' + date.getHours()).slice(-2) + ':' +
('00' + date.getMinutes()).slice(-2) + ':' +
('00' + date.getSeconds()).slice(-2) + "." +
('00' + date.getSeconds()).slice(-2) + '.' +
('00' + date.getMilliseconds()).slice(-3);
return date;
......
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