1
0
mirror of https://github.com/wulkanowy/wulkanowy.git synced 2024-09-20 00:39:08 -05:00

Add exams (#87)

* [API/exams] Fix parsing empty list
* [API/exams] Fix date format
* [API/exams] Set day name from api
This commit is contained in:
Rafał Borcz 2018-05-03 19:47:34 +02:00 committed by Mikołaj Pich
parent 1740047aea
commit ffd20c94dd
59 changed files with 1865 additions and 435 deletions

View File

@ -1,12 +1,17 @@
package io.github.wulkanowy.api.exams;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import io.github.wulkanowy.api.SnP;
import io.github.wulkanowy.api.VulcanException;
@ -22,11 +27,11 @@ public class ExamsWeek {
this.snp = snp;
}
public Week<ExamDay> getCurrent() throws IOException, VulcanException {
public Week<ExamDay> getCurrent() throws IOException, VulcanException, ParseException {
return getWeek("", true);
}
public Week<ExamDay> getWeek(String tick, final boolean onlyNotEmpty) throws IOException, VulcanException {
public Week<ExamDay> getWeek(String tick, final boolean onlyNotEmpty) throws IOException, VulcanException, ParseException {
Document examsPage = snp.getSnPPageDocument(EXAMS_PAGE_URL + tick);
Elements examsDays = examsPage.select(".mainContainer > div:not(.navigation)");
@ -41,7 +46,9 @@ public class ExamsWeek {
}
if (null != dayHeading) {
day.setDate(dayHeading.text().split(", ")[1]);
String[] dateHeader = dayHeading.text().split(", ");
day.setDayName(StringUtils.capitalize(dateHeader[0]));
day.setDate(getFormattedDate(dateHeader[1]));
}
Elements exams = item.select("article");
@ -58,8 +65,17 @@ public class ExamsWeek {
days.add(day);
}
return new Week<ExamDay>()
.setStartDayDate(examsDays.select("h2").first().text().split(" ")[1])
.setStartDayDate(getFormattedDate(examsPage.select(".mainContainer > h2")
.first().text().split(" ")[1]))
.setDays(days);
}
private String getFormattedDate(String date) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy", Locale.ROOT);
Date d = sdf.parse(date);
sdf.applyPattern("yyyy-MM-dd");
return sdf.format(d);
}
}

View File

@ -11,10 +11,6 @@ public class Day {
private String dayName = "";
private boolean isFreeDay = false;
private String freeDayName = "";
public Lesson getLesson(int index) {
return lessons.get(index);
}
@ -44,20 +40,4 @@ public class Day {
public void setDayName(String dayName) {
this.dayName = dayName;
}
public boolean isFreeDay() {
return isFreeDay;
}
public void setFreeDay(boolean freeDay) {
isFreeDay = freeDay;
}
public String getFreeDayName() {
return freeDayName;
}
public void setFreeDayName(String freeDayName) {
this.freeDayName = freeDayName;
}
}

View File

@ -14,7 +14,6 @@ import java.util.Locale;
import io.github.wulkanowy.api.SnP;
import io.github.wulkanowy.api.VulcanException;
import io.github.wulkanowy.api.generic.Day;
import io.github.wulkanowy.api.generic.Lesson;
import io.github.wulkanowy.api.generic.Week;
@ -28,25 +27,25 @@ public class Timetable {
this.snp = snp;
}
public Week<Day> getWeekTable() throws IOException, ParseException, VulcanException {
public Week<TimetableDay> getWeekTable() throws IOException, ParseException, VulcanException {
return getWeekTable("");
}
public Week<Day> getWeekTable(final String tick) throws IOException, ParseException, VulcanException {
public Week<TimetableDay> getWeekTable(final String tick) throws IOException, ParseException, VulcanException {
Element table = snp.getSnPPageDocument(TIMETABLE_PAGE_URL + tick)
.select(".mainContainer .presentData").first();
List<Day> days = getDays(table.select("thead th"));
List<TimetableDay> days = getDays(table.select("thead th"));
setLessonToDays(table, days);
return new Week<Day>()
return new Week<TimetableDay>()
.setStartDayDate(days.get(0).getDate())
.setDays(days);
}
private List<Day> getDays(Elements tableHeaderCells) throws ParseException {
List<Day> days = new ArrayList<>();
private List<TimetableDay> getDays(Elements tableHeaderCells) throws ParseException {
List<TimetableDay> days = new ArrayList<>();
for (int i = 2; i < 7; i++) {
String[] dayHeaderCell = tableHeaderCells.get(i).html().split("<br>");
@ -55,7 +54,7 @@ public class Timetable {
Date d = sdf.parse(dayHeaderCell[1].trim());
sdf.applyPattern("yyyy-MM-dd");
Day day = new Day();
TimetableDay day = new TimetableDay();
day.setDayName(dayHeaderCell[0]);
day.setDate(sdf.format(d));
@ -70,7 +69,7 @@ public class Timetable {
return days;
}
private void setLessonToDays(Element table, List<Day> days) {
private void setLessonToDays(Element table, List<TimetableDay> days) {
for (Element row : table.select("tbody tr")) {
Elements hours = row.select("td");

View File

@ -0,0 +1,26 @@
package io.github.wulkanowy.api.timetable;
import io.github.wulkanowy.api.generic.Day;
public class TimetableDay extends Day {
private boolean isFreeDay = false;
private String freeDayName = "";
public boolean isFreeDay() {
return isFreeDay;
}
public void setFreeDay(boolean freeDay) {
isFreeDay = freeDay;
}
public String getFreeDayName() {
return freeDayName;
}
public void setFreeDayName(String freeDayName) {
this.freeDayName = freeDayName;
}
}

View File

@ -12,20 +12,25 @@ public class ExamsWeekTest extends StudentAndParentTestCase {
private ExamsWeek onePerDay;
private ExamsWeek empty;
@Before
public void getCurrent() throws Exception {
onePerDay = new ExamsWeek(getSnp("Sprawdziany-one-per-day.html"));
empty = new ExamsWeek(getSnp("Sprawdziany-empty.html"));
}
@Test
public void getWeekTest() throws Exception {
Assert.assertEquals("23.10.2017", onePerDay.getCurrent().getStartDayDate());
Assert.assertEquals("2017-10-23", onePerDay.getCurrent().getStartDayDate());
Assert.assertEquals("2018-04-30", empty.getCurrent().getStartDayDate());
}
@Test
public void getDaysListTest() throws Exception {
Assert.assertEquals(3, onePerDay.getCurrent().getDays().size());
Assert.assertEquals(7, onePerDay.getWeek("", false).getDays().size());
Assert.assertEquals(0, empty.getCurrent().getDays().size());
}
@Test
@ -45,9 +50,18 @@ public class ExamsWeekTest extends StudentAndParentTestCase {
public void getDayDateTest() throws Exception {
List<ExamDay> dayList = onePerDay.getCurrent().getDays();
Assert.assertEquals("23.10.2017", dayList.get(0).getDate());
Assert.assertEquals("24.10.2017", dayList.get(1).getDate());
Assert.assertEquals("27.10.2017", dayList.get(2).getDate());
Assert.assertEquals("2017-10-23", dayList.get(0).getDate());
Assert.assertEquals("2017-10-24", dayList.get(1).getDate());
Assert.assertEquals("2017-10-27", dayList.get(2).getDate());
}
@Test
public void getDayNameTest() throws Exception {
List<ExamDay> dayList = onePerDay.getCurrent().getDays();
Assert.assertEquals("Poniedziałek", dayList.get(0).getDayName());
Assert.assertEquals("Wtorek", dayList.get(1).getDayName());
Assert.assertEquals("Piątek", dayList.get(2).getDayName());
}
@Test

View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Witryna ucznia i rodzica Terminarz sprawdzian&#243;w</title>
</head>
<body>
<main class="mainContainer">
<h1>Sprawdziany</h1>
<h2>Tydzień 30.04.2018 - 06.05.2018</h2>
<h2>Nie zaplanowano żadnych sprawdzian&#243;w na wybrany tydzień</h2>
<div class="navigation">
<a href="/symbol/123456/Sprawdziany.mvc/Terminarz?data=636600384000000000&amp;rokSzkolny=2017&amp;rodzajWidoku=2" class="button-prev">Poprzedni tydzień</a>
<a href="/symbol/123456/Sprawdziany.mvc/Terminarz?data=636612480000000000&amp;rokSzkolny=2017&amp;rodzajWidoku=2" class="button-next">Następny tydzień</a>
</div>
</main>
<footer>wersja: 17.09.0009.26859</footer>
</body>
</html>

View File

@ -62,7 +62,7 @@ android {
}
greendao {
schemaVersion 24
schemaVersion 25
generateTests = true
}

View File

@ -0,0 +1,18 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
public class ExamTest extends AbstractDaoTestLongPk<ExamDao, Exam> {
public ExamTest() {
super(ExamDao.class);
}
@Override
protected Exam createEntity(Long key) {
Exam entity = new Exam();
entity.setId(key);
return entity;
}
}

View File

@ -10,6 +10,8 @@ public interface DbContract {
Week getWeek(String date);
Week getWeek(long diaryId, String date);
List<Subject> getSubjectList(int semesterName);
List<Grade> getNewGrades(int semesterName);

View File

@ -17,7 +17,7 @@ import javax.inject.Singleton;
import io.github.wulkanowy.api.Vulcan;
import io.github.wulkanowy.data.db.dao.entities.DaoMaster;
import io.github.wulkanowy.data.db.dao.migrations.Migration23;
import io.github.wulkanowy.data.db.dao.migrations.Migration24;
import io.github.wulkanowy.data.db.dao.migrations.Migration25;
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
import io.github.wulkanowy.di.annotations.ApplicationContext;
import io.github.wulkanowy.di.annotations.DatabaseInfo;
@ -66,6 +66,7 @@ public class DbHelper extends DaoMaster.OpenHelper {
}
private void recreateDatabase(Database db) {
LogUtils.info("Database is recreating...");
sharedPref.setCurrentUserId(0);
DaoMaster.dropAllTables(db, true);
onCreate(db);
@ -74,7 +75,7 @@ public class DbHelper extends DaoMaster.OpenHelper {
private List<Migration> getMigrations() {
List<Migration> migrations = new ArrayList<>();
migrations.add(new Migration23());
migrations.add(new Migration24());
migrations.add(new Migration25());
// Sorting just to be safe, in case other people add migrations in the wrong order.
Comparator<Migration> migrationComparator = new Comparator<Migration>() {

View File

@ -32,13 +32,18 @@ public class DbRepository implements DbContract {
@Override
public Week getWeek(String date) {
return getWeek(getCurrentDiaryId(), date);
}
@Override
public Week getWeek(long diaryId, String date) {
return daoSession.getWeekDao().queryBuilder().where(
WeekDao.Properties.StartDayDate.eq(date),
WeekDao.Properties.DiaryId.eq(getCurrentDiaryId())
WeekDao.Properties.DiaryId.eq(diaryId)
).unique();
}
@Override
public List<Subject> getSubjectList(int semesterName) {
return daoSession.getSemesterDao().load(getSemesterId(semesterName)).getSubjectList();
}

View File

@ -41,6 +41,9 @@ public class Day {
@ToMany(referencedJoinProperty = "dayId")
private List<AttendanceLesson> attendanceLessons;
@ToMany(referencedJoinProperty = "dayId")
private List<Exam> exams;
/**
* Used to resolve relations
*/
@ -218,6 +221,36 @@ public class Day {
myDao.update(this);
}
/**
* To-many relationship, resolved on first access (and after reset).
* Changes to to-many relations are not persisted, make changes to the target entity.
*/
@Generated(hash = 1231531946)
public List<Exam> getExams() {
if (exams == null) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
ExamDao targetDao = daoSession.getExamDao();
List<Exam> examsNew = targetDao._queryDay_Exams(id);
synchronized (this) {
if (exams == null) {
exams = examsNew;
}
}
}
return exams;
}
/**
* Resets a to-many relationship, making the next get call to query for a fresh result.
*/
@Generated(hash = 841969952)
public synchronized void resetExams() {
exams = null;
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 1409317752)
public void __setDaoSession(DaoSession daoSession) {

View File

@ -0,0 +1,177 @@
package io.github.wulkanowy.data.db.dao.entities;
import org.greenrobot.greendao.DaoException;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Property;
import java.io.Serializable;
@Entity(
nameInDb = "Exams",
active = true
)
public class Exam implements Serializable {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "day_id")
private Long dayId;
@Property(nameInDb = "subject_and_group")
private String subjectAndGroup = "";
@Property(nameInDb = "type")
private String type = "";
@Property(nameInDb = "description")
private String description = "";
@Property(nameInDb = "teacher")
private String teacher = "";
@Property(nameInDb = "date")
private String date = "";
private static final long serialVersionUID = 42L;
/**
* Used to resolve relations
*/
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/**
* Used for active entity operations.
*/
@Generated(hash = 973692038)
private transient ExamDao myDao;
@Generated(hash = 1455345431)
public Exam(Long id, Long dayId, String subjectAndGroup, String type,
String description, String teacher, String date) {
this.id = id;
this.dayId = dayId;
this.subjectAndGroup = subjectAndGroup;
this.type = type;
this.description = description;
this.teacher = teacher;
this.date = date;
}
@Generated(hash = 945526930)
public Exam() {
}
public Long getId() {
return id;
}
public Exam setId(Long id) {
this.id = id;
return this;
}
public Long getDayId() {
return this.dayId;
}
public Exam setDayId(Long dayId) {
this.dayId = dayId;
return this;
}
public String getSubjectAndGroup() {
return subjectAndGroup;
}
public Exam setSubjectAndGroup(String subjectAndGroup) {
this.subjectAndGroup = subjectAndGroup;
return this;
}
public String getType() {
return type;
}
public Exam setType(String type) {
this.type = type;
return this;
}
public String getDescription() {
return description;
}
public Exam setDescription(String description) {
this.description = description;
return this;
}
public String getTeacher() {
return teacher;
}
public Exam setTeacher(String teacher) {
this.teacher = teacher;
return this;
}
public String getDate() {
return date;
}
public Exam setDate(String date) {
this.date = date;
return this;
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 128553479)
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 1942392019)
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 713229351)
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/**
* called by internal mechanisms, do not call yourself.
*/
@Generated(hash = 1730563422)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getExamDao() : null;
}
}

View File

@ -32,6 +32,9 @@ public class Week {
@Property(nameInDb = "timetable_synced")
private boolean timetableSynced = false;
@Property(nameInDb = "exams_synced")
private boolean examsSynced = false;
@ToMany(referencedJoinProperty = "weekId")
private List<Day> dayList;
@ -47,14 +50,15 @@ public class Week {
@Generated(hash = 1019310398)
private transient WeekDao myDao;
@Generated(hash = 1608180902)
public Week(Long id, Long diaryId, String startDayDate,
boolean attendanceSynced, boolean timetableSynced) {
@Generated(hash = 23357599)
public Week(Long id, Long diaryId, String startDayDate, boolean attendanceSynced,
boolean timetableSynced, boolean examsSynced) {
this.id = id;
this.diaryId = diaryId;
this.startDayDate = startDayDate;
this.attendanceSynced = attendanceSynced;
this.timetableSynced = timetableSynced;
this.examsSynced = examsSynced;
}
@Generated(hash = 2135529658)
@ -88,8 +92,8 @@ public class Week {
return this;
}
public boolean isAttendanceSynced() {
return attendanceSynced;
public boolean getAttendanceSynced() {
return this.attendanceSynced;
}
public Week setAttendanceSynced(boolean attendanceSynced) {
@ -97,8 +101,8 @@ public class Week {
return this;
}
public boolean isTimetableSynced() {
return timetableSynced;
public boolean getTimetableSynced() {
return this.timetableSynced;
}
public Week setTimetableSynced(boolean timetableSynced) {
@ -106,6 +110,15 @@ public class Week {
return this;
}
public Week setExamsSynced(boolean examsSynced) {
this.examsSynced = examsSynced;
return this;
}
public boolean getExamsSynced() {
return examsSynced;
}
/**
* To-many relationship, resolved on first access (and after reset).
* Changes to to-many relations are not persisted, make changes to the target entity.
@ -172,14 +185,6 @@ public class Week {
myDao.update(this);
}
public boolean getAttendanceSynced() {
return this.attendanceSynced;
}
public boolean getTimetableSynced() {
return this.timetableSynced;
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 665278367)
public void __setDaoSession(DaoSession daoSession) {

View File

@ -6,11 +6,11 @@ import io.github.wulkanowy.api.Vulcan;
import io.github.wulkanowy.data.db.dao.DbHelper;
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
public class Migration24 implements DbHelper.Migration {
public class Migration25 implements DbHelper.Migration {
@Override
public Integer getVersion() {
return 24;
return 25;
}
@Override

View File

@ -0,0 +1,147 @@
package io.github.wulkanowy.data.sync;
import org.threeten.bp.LocalDate;
import org.threeten.bp.format.DateTimeFormatter;
import org.threeten.bp.format.TextStyle;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.inject.Inject;
import io.github.wulkanowy.api.Vulcan;
import io.github.wulkanowy.api.VulcanException;
import io.github.wulkanowy.api.exams.ExamDay;
import io.github.wulkanowy.data.db.dao.entities.DaoSession;
import io.github.wulkanowy.data.db.dao.entities.Day;
import io.github.wulkanowy.data.db.dao.entities.DayDao;
import io.github.wulkanowy.data.db.dao.entities.Exam;
import io.github.wulkanowy.data.db.dao.entities.ExamDao;
import io.github.wulkanowy.data.db.dao.entities.Week;
import io.github.wulkanowy.data.db.dao.entities.WeekDao;
import io.github.wulkanowy.utils.AppConstant;
import io.github.wulkanowy.utils.DataObjectConverter;
import io.github.wulkanowy.utils.LogUtils;
import io.github.wulkanowy.utils.TimeUtils;
public class ExamsSync {
private final DaoSession daoSession;
private final Vulcan vulcan;
private long diaryId;
@Inject
ExamsSync(DaoSession daoSession, Vulcan vulcan) {
this.daoSession = daoSession;
this.vulcan = vulcan;
}
public void syncExams(long diaryId, String date) throws IOException, VulcanException,
ParseException {
this.diaryId = diaryId;
io.github.wulkanowy.api.generic.Week<ExamDay> weekApi = getWeekFromApi(getNormalizedDate(date));
Week weekDb = getWeekFromDb(weekApi.getStartDayDate());
long weekId = updateWeekInDb(weekDb, weekApi);
List<Exam> examList = getPreparedExams(weekApi.getDays(), weekId);
daoSession.getExamDao().saveInTx(examList);
LogUtils.debug("Synchronization exams (amount = " + examList.size() + ")");
}
private Week getWeekFromDb(String date) {
return daoSession.getWeekDao().queryBuilder().where(
WeekDao.Properties.DiaryId.eq(diaryId),
WeekDao.Properties.StartDayDate.eq(date)
).unique();
}
private io.github.wulkanowy.api.generic.Week<ExamDay> getWeekFromApi(String date)
throws VulcanException, IOException, ParseException {
return vulcan.getExamsList().getWeek(date, true);
}
private Long updateWeekInDb(Week weekDb, io.github.wulkanowy.api.generic.Week weekApi) {
if (weekDb != null) {
weekDb.setExamsSynced(true);
weekDb.update();
return weekDb.getId();
}
Week weekApiEntity = DataObjectConverter.weekToWeekEntity(weekApi).setDiaryId(diaryId);
weekApiEntity.setExamsSynced(true);
return daoSession.getWeekDao().insert(weekApiEntity);
}
private String getNormalizedDate(String date) throws ParseException {
return null != date ? String.valueOf(TimeUtils.getNetTicks(date)) : "";
}
private Day getDayFromDb(String date, long weekId) {
return daoSession.getDayDao().queryBuilder().where(
DayDao.Properties.WeekId.eq(weekId),
DayDao.Properties.Date.eq(date)
).unique();
}
private List<Exam> getPreparedExams(List<ExamDay> dayListFromApi,
long weekId) {
List<Exam> preparedExamList = new ArrayList<>();
for (ExamDay dayFromApi : dayListFromApi) {
Day dayDb = getDayFromDb(dayFromApi.getDate(), weekId);
Day dayApiEntity = DataObjectConverter.dayToDayEntity(dayFromApi);
long dayId = updateDayInDb(dayDb, dayApiEntity, weekId);
prepareExam(dayFromApi.getExamList(), preparedExamList, dayId);
}
return preparedExamList;
}
private long updateDayInDb(Day dayDb, Day dayApi, long weekId) {
dayApi.setWeekId(weekId);
if (null != dayDb) {
return dayDb.getId();
}
return daoSession.getDayDao().insert(dayApi);
}
private void prepareExam(List<io.github.wulkanowy.api.exams.Exam> examList,
List<Exam> preparedExams, long dayId) {
List<Exam> examsApiEntity = DataObjectConverter.examsToExamsEntitiy(examList);
for (Exam examApi : examsApiEntity) {
Exam examDb = getExamFromDb(examApi, dayId);
examApi.setDayId(dayId);
if (examDb != null) {
examApi.setId(examDb.getId());
}
preparedExams.add(examApi);
}
}
private Exam getExamFromDb(Exam examApi, long dayId) {
return daoSession.getExamDao().queryBuilder()
.where(ExamDao.Properties.DayId.eq(dayId),
ExamDao.Properties.Date.eq(examApi.getDate()),
ExamDao.Properties.SubjectAndGroup.eq(examApi.getSubjectAndGroup()),
ExamDao.Properties.Teacher.eq(examApi.getTeacher()))
.unique();
}
}

View File

@ -32,5 +32,9 @@ public interface SyncContract {
void syncTimetable(long diaryId, String date) throws VulcanException, IOException, ParseException;
void syncExams() throws VulcanException, IOException, ParseException;
void syncExams(long diaryId, String date) throws VulcanException, IOException, ParseException;
void syncAll() throws VulcanException, IOException, ParseException;
}

View File

@ -23,16 +23,20 @@ public class SyncRepository implements SyncContract {
private final AccountSync accountSync;
private final ExamsSync examsSync;
private final DbContract database;
@Inject
SyncRepository(GradeSync gradeSync, SubjectSync subjectSync, AttendanceSync attendanceSync,
TimetableSync timetableSync, AccountSync accountSync, DbContract database) {
TimetableSync timetableSync, AccountSync accountSync, ExamsSync examsSync,
DbContract database) {
this.gradeSync = gradeSync;
this.subjectSync = subjectSync;
this.attendanceSync = attendanceSync;
this.timetableSync = timetableSync;
this.accountSync = accountSync;
this.examsSync = examsSync;
this.database = database;
}
@ -95,11 +99,26 @@ public class SyncRepository implements SyncContract {
}
}
@Override
public void syncExams() throws VulcanException, IOException, ParseException {
examsSync.syncExams(database.getCurrentDiaryId(), null);
}
@Override
public void syncExams(long diaryId, String date) throws VulcanException, IOException, ParseException {
if (diaryId != 0) {
examsSync.syncExams(diaryId, date);
} else {
examsSync.syncExams(database.getCurrentDiaryId(), date);
}
}
@Override
public void syncAll() throws VulcanException, IOException, ParseException {
syncSubjects();
syncGrades();
syncAttendance();
syncTimetable();
syncExams();
}
}

View File

@ -40,7 +40,7 @@ public class TimetableSync {
public void syncTimetable(long diaryId, String date) throws IOException, ParseException, VulcanException {
this.diaryId = diaryId;
io.github.wulkanowy.api.generic.Week<io.github.wulkanowy.api.generic.Day> weekApi = getWeekFromApi(getNormalizedDate(date));
io.github.wulkanowy.api.generic.Week<io.github.wulkanowy.api.timetable.TimetableDay> weekApi = getWeekFromApi(getNormalizedDate(date));
Week weekDb = getWeekFromDb(weekApi.getStartDayDate());
long weekId = updateWeekInDb(weekDb, weekApi);
@ -56,7 +56,7 @@ public class TimetableSync {
return null != date ? String.valueOf(TimeUtils.getNetTicks(date)) : "";
}
private io.github.wulkanowy.api.generic.Week<io.github.wulkanowy.api.generic.Day> getWeekFromApi(String date)
private io.github.wulkanowy.api.generic.Week<io.github.wulkanowy.api.timetable.TimetableDay> getWeekFromApi(String date)
throws IOException, ParseException, VulcanException {
return vulcan.getTimetable().getWeekTable(date);
}
@ -82,14 +82,14 @@ public class TimetableSync {
return daoSession.getWeekDao().insert(apiEntity);
}
private List<TimetableLesson> updateDays(List<io.github.wulkanowy.api.generic.Day> dayListFromApi, long weekId) {
private List<TimetableLesson> updateDays(List<io.github.wulkanowy.api.timetable.TimetableDay> dayListFromApi, long weekId) {
List<TimetableLesson> updatedLessonList = new ArrayList<>();
for (io.github.wulkanowy.api.generic.Day dayFromApi : dayListFromApi) {
for (io.github.wulkanowy.api.timetable.TimetableDay dayFromApi : dayListFromApi) {
Day dbDayEntity = getDayFromDb(dayFromApi.getDate(), weekId);
Day apiDayEntity = DataObjectConverter.dayToDayEntity(dayFromApi);
Day apiDayEntity = DataObjectConverter.timetableDayToDayEntity(dayFromApi);
long dayId = updateDay(dbDayEntity, apiDayEntity, weekId);

View File

@ -5,7 +5,8 @@ import io.github.wulkanowy.di.annotations.PerFragment;
import io.github.wulkanowy.di.modules.FragmentModule;
import io.github.wulkanowy.ui.main.attendance.AttendanceFragment;
import io.github.wulkanowy.ui.main.attendance.AttendanceTabFragment;
import io.github.wulkanowy.ui.main.dashboard.DashboardFragment;
import io.github.wulkanowy.ui.main.exams.ExamsFragment;
import io.github.wulkanowy.ui.main.exams.ExamsTabFragment;
import io.github.wulkanowy.ui.main.grades.GradesFragment;
import io.github.wulkanowy.ui.main.timetable.TimetableFragment;
import io.github.wulkanowy.ui.main.timetable.TimetableTabFragment;
@ -20,7 +21,9 @@ public interface FragmentComponent {
void inject(AttendanceTabFragment attendanceTabFragment);
void inject(DashboardFragment dashboardFragment);
void inject(ExamsFragment examsFragment);
void inject(ExamsTabFragment examsTabFragment);
void inject(TimetableFragment timetableFragment);

View File

@ -8,10 +8,10 @@ import dagger.Module;
import dagger.Provides;
import io.github.wulkanowy.di.annotations.ActivityContext;
import io.github.wulkanowy.di.annotations.PerActivity;
import io.github.wulkanowy.ui.base.BasePagerAdapter;
import io.github.wulkanowy.ui.login.LoginContract;
import io.github.wulkanowy.ui.login.LoginPresenter;
import io.github.wulkanowy.ui.main.MainContract;
import io.github.wulkanowy.ui.main.MainPagerAdapter;
import io.github.wulkanowy.ui.main.MainPresenter;
import io.github.wulkanowy.ui.splash.SplashContract;
import io.github.wulkanowy.ui.splash.SplashPresenter;
@ -58,7 +58,7 @@ public class ActivityModule {
}
@Provides
MainPagerAdapter provideMainPagerAdapter() {
return new MainPagerAdapter(activity.getSupportFragmentManager());
BasePagerAdapter provideMainPagerAdapter() {
return new BasePagerAdapter(activity.getSupportFragmentManager());
}
}

View File

@ -6,20 +6,22 @@ import dagger.Module;
import dagger.Provides;
import eu.davidea.flexibleadapter.FlexibleAdapter;
import io.github.wulkanowy.di.annotations.PerFragment;
import io.github.wulkanowy.ui.base.BasePagerAdapter;
import io.github.wulkanowy.ui.main.attendance.AttendanceContract;
import io.github.wulkanowy.ui.main.attendance.AttendanceHeaderItem;
import io.github.wulkanowy.ui.main.attendance.AttendancePagerAdapter;
import io.github.wulkanowy.ui.main.attendance.AttendancePresenter;
import io.github.wulkanowy.ui.main.attendance.AttendanceTabContract;
import io.github.wulkanowy.ui.main.attendance.AttendanceTabPresenter;
import io.github.wulkanowy.ui.main.dashboard.DashboardContract;
import io.github.wulkanowy.ui.main.dashboard.DashboardPresenter;
import io.github.wulkanowy.ui.main.exams.ExamsContract;
import io.github.wulkanowy.ui.main.exams.ExamsPresenter;
import io.github.wulkanowy.ui.main.exams.ExamsSubItem;
import io.github.wulkanowy.ui.main.exams.ExamsTabContract;
import io.github.wulkanowy.ui.main.exams.ExamsTabPresenter;
import io.github.wulkanowy.ui.main.grades.GradeHeaderItem;
import io.github.wulkanowy.ui.main.grades.GradesContract;
import io.github.wulkanowy.ui.main.grades.GradesPresenter;
import io.github.wulkanowy.ui.main.timetable.TimetableContract;
import io.github.wulkanowy.ui.main.timetable.TimetableHeaderItem;
import io.github.wulkanowy.ui.main.timetable.TimetablePagerAdapter;
import io.github.wulkanowy.ui.main.timetable.TimetablePresenter;
import io.github.wulkanowy.ui.main.timetable.TimetableTabContract;
import io.github.wulkanowy.ui.main.timetable.TimetableTabPresenter;
@ -47,8 +49,8 @@ public class FragmentModule {
@PerFragment
@Provides
DashboardContract.Presenter provideDashboardPresenter(DashboardPresenter dashboardPresenter) {
return dashboardPresenter;
ExamsContract.Presenter provideDashboardPresenter(ExamsPresenter examsPresenter) {
return examsPresenter;
}
@PerFragment
@ -58,8 +60,8 @@ public class FragmentModule {
}
@Provides
AttendancePagerAdapter provideAttendancePagerAdapter() {
return new AttendancePagerAdapter(fragment.getChildFragmentManager());
BasePagerAdapter provideBasePagerAdapter() {
return new BasePagerAdapter(fragment.getChildFragmentManager());
}
@Provides
@ -67,6 +69,21 @@ public class FragmentModule {
return new FlexibleAdapter<>(null);
}
@Provides
FlexibleAdapter<TimetableHeaderItem> provideTimetableTabAdapter() {
return new FlexibleAdapter<>(null);
}
@Provides
FlexibleAdapter<GradeHeaderItem> provideGradesAdapter() {
return new FlexibleAdapter<>(null);
}
@Provides
FlexibleAdapter<ExamsSubItem> provideExamAdapter() {
return new FlexibleAdapter<>(null);
}
@PerFragment
@Provides
TimetableContract.Presenter provideTimetablePresenter(TimetablePresenter timetablePresenter) {
@ -80,17 +97,7 @@ public class FragmentModule {
}
@Provides
TimetablePagerAdapter provideTimetablePagerAdapter() {
return new TimetablePagerAdapter(fragment.getChildFragmentManager());
}
@Provides
FlexibleAdapter<TimetableHeaderItem> provideTimetableTabAdapter() {
return new FlexibleAdapter<>(null);
}
@Provides
FlexibleAdapter<GradeHeaderItem> provideGradesAdapter() {
return new FlexibleAdapter<>(null);
ExamsTabContract.Presenter provideExamsTabPresenter(ExamsTabPresenter examsTabPresenter) {
return examsTabPresenter;
}
}

View File

@ -0,0 +1,47 @@
package io.github.wulkanowy.ui.base;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import java.util.ArrayList;
import java.util.List;
public class BasePagerAdapter extends FragmentStatePagerAdapter {
private List<Fragment> fragmentList = new ArrayList<>();
private List<String> titleList = new ArrayList<>();
public BasePagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
public void addFragment(@NonNull Fragment fragment, @NonNull String title) {
fragmentList.add(fragment);
titleList.add(title);
}
public void addFragment(@NonNull Fragment fragment) {
fragmentList.add(fragment);
}
@Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override
public int getCount() {
return fragmentList.size();
}
@Override
public CharSequence getPageTitle(int position) {
if (!titleList.isEmpty()) {
return titleList.get(position);
}
return null;
}
}

View File

@ -18,8 +18,9 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import io.github.wulkanowy.R;
import io.github.wulkanowy.ui.base.BaseActivity;
import io.github.wulkanowy.ui.base.BasePagerAdapter;
import io.github.wulkanowy.ui.main.attendance.AttendanceFragment;
import io.github.wulkanowy.ui.main.dashboard.DashboardFragment;
import io.github.wulkanowy.ui.main.exams.ExamsFragment;
import io.github.wulkanowy.ui.main.grades.GradesFragment;
import io.github.wulkanowy.ui.main.settings.SettingsFragment;
import io.github.wulkanowy.ui.main.timetable.TimetableFragment;
@ -39,7 +40,7 @@ public class MainActivity extends BaseActivity implements MainContract.View,
View progressBar;
@Inject
MainPagerAdapter pagerAdapter;
BasePagerAdapter pagerAdapter;
@Inject
MainContract.Presenter presenter;
@ -107,8 +108,8 @@ public class MainActivity extends BaseActivity implements MainContract.View,
bottomNavigation.addItem(new AHBottomNavigationItem(getString(R.string.attendance_text),
R.drawable.ic_menu_attendance_24dp));
bottomNavigation.addItem(new AHBottomNavigationItem(getString(R.string.dashboard_text),
R.drawable.ic_menu_dashboard_24dp));
bottomNavigation.addItem(new AHBottomNavigationItem(getString(R.string.exams_text),
R.drawable.ic_menu_exams_24dp));
bottomNavigation.addItem(new AHBottomNavigationItem(getString(R.string.timetable_text),
R.drawable.ic_menu_timetable_24dp));
@ -129,7 +130,7 @@ public class MainActivity extends BaseActivity implements MainContract.View,
public void initiationViewPager(int tabPosition) {
pagerAdapter.addFragment(new GradesFragment());
pagerAdapter.addFragment(new AttendanceFragment());
pagerAdapter.addFragment(new DashboardFragment());
pagerAdapter.addFragment(new ExamsFragment());
pagerAdapter.addFragment(new TimetableFragment());
pagerAdapter.addFragment(new SettingsFragment());

View File

@ -1,31 +0,0 @@
package io.github.wulkanowy.ui.main;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import java.util.ArrayList;
import java.util.List;
public class MainPagerAdapter extends FragmentStatePagerAdapter {
private List<Fragment> fragmentList = new ArrayList<>();
public MainPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
void addFragment(Fragment fragment) {
fragmentList.add(fragment);
}
@Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override
public int getCount() {
return fragmentList.size();
}
}

View File

@ -1,37 +0,0 @@
package io.github.wulkanowy.ui.main;
import android.support.v4.app.Fragment;
import java.util.ArrayList;
import java.util.List;
public class TabsData {
private List<Fragment> fragments = new ArrayList<>();
private List<String> titles = new ArrayList<>();
public Fragment getFragment(int index) {
return fragments.get(index);
}
public void addFragment(Fragment fragment) {
if (fragment != null) {
fragments.add(fragment);
}
}
public int getFragmentsCount() {
return fragments.size();
}
public String getTitle(int index) {
return titles.get(index);
}
public void addTitle(String title) {
if (title != null) {
titles.add(title);
}
}
}

View File

@ -3,7 +3,6 @@ package io.github.wulkanowy.ui.main.attendance;
import io.github.wulkanowy.di.annotations.PerActivity;
import io.github.wulkanowy.ui.base.BaseContract;
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
import io.github.wulkanowy.ui.main.TabsData;
public interface AttendanceContract {
@ -13,7 +12,7 @@ public interface AttendanceContract {
void scrollViewPagerToPosition(int position);
void setTabDataToAdapter(TabsData tabsData);
void setTabDataToAdapter(String date);
void setAdapterWithTabLayout();

View File

@ -17,8 +17,8 @@ import butterknife.ButterKnife;
import io.github.wulkanowy.R;
import io.github.wulkanowy.di.component.FragmentComponent;
import io.github.wulkanowy.ui.base.BaseFragment;
import io.github.wulkanowy.ui.base.BasePagerAdapter;
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
import io.github.wulkanowy.ui.main.TabsData;
public class AttendanceFragment extends BaseFragment implements AttendanceContract.View {
@ -31,7 +31,7 @@ public class AttendanceFragment extends BaseFragment implements AttendanceContra
TabLayout tabLayout;
@Inject
AttendancePagerAdapter pagerAdapter;
BasePagerAdapter pagerAdapter;
@Inject
AttendanceContract.Presenter presenter;
@ -65,8 +65,8 @@ public class AttendanceFragment extends BaseFragment implements AttendanceContra
}
@Override
public void setTabDataToAdapter(TabsData tabsData) {
pagerAdapter.setTabsData(tabsData);
public void setTabDataToAdapter(String date) {
pagerAdapter.addFragment(AttendanceTabFragment.newInstance(date), date);
}
@Override

View File

@ -1,38 +0,0 @@
package io.github.wulkanowy.ui.main.attendance;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import io.github.wulkanowy.ui.main.TabsData;
public class AttendancePagerAdapter extends FragmentStatePagerAdapter {
private TabsData tabsData;
public AttendancePagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
void setTabsData(TabsData tabsData) {
this.tabsData = tabsData;
}
@Override
public Fragment getItem(int position) {
return tabsData.getFragment(position);
}
@Override
public int getCount() {
return tabsData.getFragmentsCount();
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return tabsData.getTitle(position);
}
}

View File

@ -8,7 +8,6 @@ import javax.inject.Inject;
import io.github.wulkanowy.data.RepositoryContract;
import io.github.wulkanowy.ui.base.BasePresenter;
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
import io.github.wulkanowy.ui.main.TabsData;
import io.github.wulkanowy.utils.TimeUtils;
import io.github.wulkanowy.utils.async.AbstractTask;
import io.github.wulkanowy.utils.async.AsyncListeners;
@ -20,8 +19,6 @@ public class AttendancePresenter extends BasePresenter<AttendanceContract.View>
private List<String> dates = new ArrayList<>();
private TabsData tabsData = new TabsData();
private OnFragmentIsReadyListener listener;
private int positionToScroll = 0;
@ -69,8 +66,7 @@ public class AttendancePresenter extends BasePresenter<AttendanceContract.View>
@Override
public void onDoInBackgroundLoading() throws Exception {
for (String date : dates) {
tabsData.addTitle(date);
tabsData.addFragment(AttendanceTabFragment.newInstance(date));
getView().setTabDataToAdapter(date);
}
}
@ -83,7 +79,6 @@ public class AttendancePresenter extends BasePresenter<AttendanceContract.View>
@Override
public void onEndLoadingAsync(boolean result, Exception exception) {
if (result) {
getView().setTabDataToAdapter(tabsData);
getView().setAdapterWithTabLayout();
getView().scrollViewPagerToPosition(positionToScroll);
listener.onFragmentIsReady();

View File

@ -100,6 +100,7 @@ public class AttendanceTabPresenter extends BasePresenter<AttendanceTabContract.
week = getRepository().getDbRepo().getWeek(date);
}
week.resetDayList();
List<Day> dayList = week.getDayList();
headerItems = new ArrayList<>();

View File

@ -1,48 +0,0 @@
package io.github.wulkanowy.ui.main.dashboard;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import javax.inject.Inject;
import butterknife.ButterKnife;
import io.github.wulkanowy.R;
import io.github.wulkanowy.di.component.FragmentComponent;
import io.github.wulkanowy.ui.base.BaseFragment;
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
public class DashboardFragment extends BaseFragment implements DashboardContract.View {
@Inject
DashboardContract.Presenter presenter;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_board, container, false);
FragmentComponent component = getFragmentComponent();
if (component != null) {
component.inject(this);
setButterKnife(ButterKnife.bind(this, view));
presenter.onStart(this, (OnFragmentIsReadyListener) getActivity());
}
return view;
}
@Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
if (presenter != null) {
presenter.onFragmentVisible(menuVisible);
}
}
@Override
public void setActivityTitle() {
setTitle(getString(R.string.dashboard_text));
}
}

View File

@ -1,37 +0,0 @@
package io.github.wulkanowy.ui.main.dashboard;
import javax.inject.Inject;
import io.github.wulkanowy.data.RepositoryContract;
import io.github.wulkanowy.ui.base.BasePresenter;
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
public class DashboardPresenter extends BasePresenter<DashboardContract.View>
implements DashboardContract.Presenter {
private OnFragmentIsReadyListener listener;
@Inject
DashboardPresenter(RepositoryContract repository) {
super(repository);
}
@Override
public void onStart(DashboardContract.View view, OnFragmentIsReadyListener listener) {
super.onStart(view);
this.listener = listener;
if (getView().isMenuVisible()) {
getView().setActivityTitle();
}
this.listener.onFragmentIsReady();
}
@Override
public void onFragmentVisible(boolean isVisible) {
if (isVisible) {
getView().setActivityTitle();
}
}
}

View File

@ -1,16 +1,22 @@
package io.github.wulkanowy.ui.main.dashboard;
package io.github.wulkanowy.ui.main.exams;
import io.github.wulkanowy.di.annotations.PerActivity;
import io.github.wulkanowy.ui.base.BaseContract;
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
public interface DashboardContract {
public interface ExamsContract {
interface View extends BaseContract.View {
void setActivityTitle();
boolean isMenuVisible();
void scrollViewPagerToPosition(int position);
void setTabDataToAdapter(String date);
void setAdapterWithTabLayout();
}
@PerActivity
@ -18,6 +24,8 @@ public interface DashboardContract {
void onStart(View view, OnFragmentIsReadyListener listener);
void onFragmentVisible(boolean isVisible);
void onFragmentActivated(boolean isVisible);
void setRestoredPosition(int position);
}
}

View File

@ -0,0 +1,81 @@
package io.github.wulkanowy.ui.main.exams;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import io.github.wulkanowy.R;
import io.github.wulkanowy.data.db.dao.entities.Exam;
public class ExamsDialogFragment extends DialogFragment {
private static final String ARGUMENT_KEY = "Item";
private Exam exam;
@BindView(R.id.exams_dialog_subject_value)
TextView subject;
@BindView(R.id.exams_dialog_type_value)
TextView type;
@BindView(R.id.exams_dialog_teacher_value)
TextView teacher;
@BindView(R.id.exams_dialog_date_value)
TextView date;
@BindView(R.id.exams_dialog_description_value)
TextView description;
public static ExamsDialogFragment newInstance(Exam exam) {
ExamsDialogFragment dialogFragment = new ExamsDialogFragment();
Bundle bundle = new Bundle();
bundle.putSerializable(ARGUMENT_KEY, exam);
dialogFragment.setArguments(bundle);
return dialogFragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
exam = (Exam) getArguments().getSerializable(ARGUMENT_KEY);
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.exams_dialog, container, false);
ButterKnife.bind(this, view);
subject.setText(exam.getSubjectAndGroup());
teacher.setText(exam.getTeacher());
type.setText(exam.getType());
date.setText(exam.getDate());
if (!exam.getDescription().isEmpty()) {
description.setText(exam.getDescription());
}
return view;
}
@OnClick(R.id.exams_dialog_close)
void onClickCloseButton() {
dismiss();
}
}

View File

@ -0,0 +1,92 @@
package io.github.wulkanowy.ui.main.exams;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.github.wulkanowy.R;
import io.github.wulkanowy.di.component.FragmentComponent;
import io.github.wulkanowy.ui.base.BaseFragment;
import io.github.wulkanowy.ui.base.BasePagerAdapter;
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
public class ExamsFragment extends BaseFragment implements ExamsContract.View {
@BindView(R.id.exams_fragment_viewpager)
ViewPager viewPager;
@BindView(R.id.exams_fragment_tab_layout)
TabLayout tabLayout;
@Inject
BasePagerAdapter pagerAdapter;
@Inject
ExamsContract.Presenter presenter;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_exams, container, false);
FragmentComponent component = getFragmentComponent();
if (component != null) {
component.inject(this);
setButterKnife(ButterKnife.bind(this, view));
presenter.onStart(this, (OnFragmentIsReadyListener) getActivity());
}
return view;
}
@Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
if (presenter != null) {
presenter.onFragmentActivated(menuVisible);
}
}
@Override
public void onError(String message) {
if (getActivity() != null) {
Snackbar.make(getActivity().findViewById(R.id.main_activity_view_pager),
message, Snackbar.LENGTH_LONG).show();
}
}
@Override
public void setActivityTitle() {
setTitle(getString(R.string.exams_text));
}
@Override
public void scrollViewPagerToPosition(int position) {
viewPager.setCurrentItem(position, false);
}
@Override
public void setTabDataToAdapter(String date) {
pagerAdapter.addFragment(ExamsTabFragment.newInstance(date), date);
}
@Override
public void setAdapterWithTabLayout() {
viewPager.setAdapter(pagerAdapter);
tabLayout.setupWithViewPager(viewPager);
}
@Override
public void onDestroyView() {
super.onDestroyView();
presenter.onDestroy();
}
}

View File

@ -0,0 +1,82 @@
package io.github.wulkanowy.ui.main.exams;
import android.view.View;
import android.widget.TextView;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import eu.davidea.flexibleadapter.FlexibleAdapter;
import eu.davidea.flexibleadapter.items.AbstractHeaderItem;
import eu.davidea.flexibleadapter.items.IFlexible;
import eu.davidea.viewholders.FlexibleViewHolder;
import io.github.wulkanowy.R;
import io.github.wulkanowy.data.db.dao.entities.Day;
public class ExamsHeaderItem extends AbstractHeaderItem<ExamsHeaderItem.HeaderVieHolder> {
private Day day;
public ExamsHeaderItem(Day day) {
this.day = day;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ExamsHeaderItem that = (ExamsHeaderItem) o;
return new EqualsBuilder()
.append(day, that.day)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(day)
.toHashCode();
}
@Override
public int getLayoutRes() {
return R.layout.exams_header;
}
@Override
public HeaderVieHolder createViewHolder(View view, FlexibleAdapter<IFlexible> adapter) {
return new HeaderVieHolder(view, adapter);
}
@Override
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, HeaderVieHolder holder, int position, List<Object> payloads) {
holder.onBind(day);
}
static class HeaderVieHolder extends FlexibleViewHolder {
@BindView(R.id.exams_header_name)
TextView name;
@BindView(R.id.exams_header_date)
TextView date;
HeaderVieHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
}
void onBind(Day item) {
name.setText(StringUtils.capitalize(item.getDayName()));
date.setText(item.getDate());
}
}
}

View File

@ -0,0 +1,102 @@
package io.github.wulkanowy.ui.main.exams;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import io.github.wulkanowy.data.RepositoryContract;
import io.github.wulkanowy.ui.base.BasePresenter;
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
import io.github.wulkanowy.utils.TimeUtils;
import io.github.wulkanowy.utils.async.AbstractTask;
import io.github.wulkanowy.utils.async.AsyncListeners;
public class ExamsPresenter extends BasePresenter<ExamsContract.View>
implements ExamsContract.Presenter, AsyncListeners.OnFirstLoadingListener {
private AbstractTask loadingTask;
private List<String> dates = new ArrayList<>();
private OnFragmentIsReadyListener listener;
private int positionToScroll = 0;
private boolean isFirstSight = false;
@Inject
ExamsPresenter(RepositoryContract repository) {
super(repository);
}
@Override
public void onStart(ExamsContract.View view, OnFragmentIsReadyListener listener) {
super.onStart(view);
this.listener = listener;
if (getView().isMenuVisible()) {
getView().setActivityTitle();
}
if (dates.isEmpty()) {
dates = TimeUtils.getMondaysFromCurrentSchoolYear();
}
if (positionToScroll == 0) {
positionToScroll = dates.indexOf(TimeUtils.getDateOfCurrentMonday(true));
}
if (!isFirstSight) {
isFirstSight = true;
loadingTask = new AbstractTask();
loadingTask.setOnFirstLoadingListener(this);
loadingTask.execute();
}
}
@Override
public void onFragmentActivated(boolean isVisible) {
if (isVisible) {
getView().setActivityTitle();
}
}
@Override
public void setRestoredPosition(int position) {
this.positionToScroll = position;
}
@Override
public void onDoInBackgroundLoading() throws Exception {
for (String date : dates) {
getView().setTabDataToAdapter(date);
}
}
@Override
public void onCanceledLoadingAsync() {
// do nothing
}
@Override
public void onEndLoadingAsync(boolean result, Exception exception) {
if (result) {
getView().setAdapterWithTabLayout();
getView().scrollViewPagerToPosition(positionToScroll);
listener.onFragmentIsReady();
}
}
@Override
public void onDestroy() {
isFirstSight = false;
if (loadingTask != null) {
loadingTask.cancel(true);
loadingTask = null;
}
super.onDestroy();
}
}

View File

@ -0,0 +1,108 @@
package io.github.wulkanowy.ui.main.exams;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.widget.TextView;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import eu.davidea.flexibleadapter.FlexibleAdapter;
import eu.davidea.flexibleadapter.items.AbstractSectionableItem;
import eu.davidea.flexibleadapter.items.IFlexible;
import eu.davidea.viewholders.FlexibleViewHolder;
import io.github.wulkanowy.R;
import io.github.wulkanowy.data.db.dao.entities.Exam;
public class ExamsSubItem
extends AbstractSectionableItem<ExamsSubItem.SubItemViewHolder, ExamsHeaderItem> {
private Exam exam;
ExamsSubItem(ExamsHeaderItem header, Exam exam) {
super(header);
this.exam = exam;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ExamsSubItem that = (ExamsSubItem) o;
return new EqualsBuilder()
.append(exam, that.exam)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(exam)
.toHashCode();
}
@Override
public int getLayoutRes() {
return R.layout.exams_subitem;
}
@Override
public SubItemViewHolder createViewHolder(View view, FlexibleAdapter<IFlexible> adapter) {
return new SubItemViewHolder(view, adapter);
}
@Override
public void bindViewHolder(FlexibleAdapter<IFlexible> adapter, SubItemViewHolder holder, int position, List<Object> payloads) {
holder.onBind(exam);
}
static class SubItemViewHolder extends FlexibleViewHolder {
@BindView(R.id.exams_subitem_subject)
TextView subject;
@BindView(R.id.exams_subitems_teacher)
TextView teacher;
@BindView(R.id.exams_subitems_type)
TextView type;
private Exam item;
SubItemViewHolder(View view, FlexibleAdapter adapter) {
super(view, adapter);
ButterKnife.bind(this, view);
view.setOnClickListener(this);
}
void onBind(Exam exam) {
item = exam;
subject.setText(item.getSubjectAndGroup());
teacher.setText(item.getTeacher());
type.setText(item.getType());
}
@Override
public void onClick(View view) {
super.onClick(view);
showDialog();
}
private void showDialog() {
ExamsDialogFragment dialogFragment = ExamsDialogFragment.newInstance(item);
dialogFragment.setStyle(DialogFragment.STYLE_NO_TITLE, 0);
dialogFragment.show(((FragmentActivity) getContentView().getContext()).getSupportFragmentManager(),
item.toString());
}
}
}

View File

@ -0,0 +1,32 @@
package io.github.wulkanowy.ui.main.exams;
import java.util.List;
import io.github.wulkanowy.di.annotations.PerFragment;
import io.github.wulkanowy.ui.base.BaseContract;
public interface ExamsTabContract {
interface View extends BaseContract.View {
void onRefreshSuccess();
void hideRefreshingBar();
void showNoItem(boolean show);
void showProgressBar(boolean show);
void updateAdapterList(List<ExamsSubItem> headerItems);
}
@PerFragment
interface Presenter extends BaseContract.Presenter<View> {
void onFragmentActivated(boolean isSelected);
void setArgumentDate(String date);
void onRefresh();
}
}

View File

@ -0,0 +1,141 @@
package io.github.wulkanowy.ui.main.exams;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import eu.davidea.flexibleadapter.FlexibleAdapter;
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager;
import io.github.wulkanowy.R;
import io.github.wulkanowy.di.component.FragmentComponent;
import io.github.wulkanowy.ui.base.BaseFragment;
public class ExamsTabFragment extends BaseFragment implements ExamsTabContract.View,
SwipeRefreshLayout.OnRefreshListener {
private static final String ARGUMENT_KEY = "date";
@BindView(R.id.exams_tab_fragment_recycler)
RecyclerView recyclerView;
@BindView(R.id.exams_tab_fragment_swipe_refresh)
SwipeRefreshLayout refreshLayout;
@BindView(R.id.exams_tab_fragment_progress_bar)
View progressBar;
@BindView(R.id.exams_tab_fragment_no_item_container)
View noItemView;
@Inject
ExamsTabContract.Presenter presenter;
@Inject
FlexibleAdapter<ExamsSubItem> adapter;
private boolean isFragmentVisible = false;
public static ExamsTabFragment newInstance(String date) {
ExamsTabFragment tabFragment = new ExamsTabFragment();
Bundle bundle = new Bundle();
bundle.putString(ARGUMENT_KEY, date);
tabFragment.setArguments(bundle);
return tabFragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_exams_tab, container, false);
FragmentComponent component = getFragmentComponent();
if (component != null) {
component.inject(this);
setButterKnife(ButterKnife.bind(this, view));
if (getArguments() != null) {
presenter.setArgumentDate(getArguments().getString(ARGUMENT_KEY));
}
presenter.onStart(this);
presenter.onFragmentActivated(isFragmentVisible);
}
return view;
}
@Override
protected void setUpOnViewCreated(View fragmentView) {
adapter.setDisplayHeadersAtStartUp(true);
recyclerView.setLayoutManager(new SmoothScrollLinearLayoutManager(fragmentView.getContext()));
recyclerView.setAdapter(adapter);
refreshLayout.setColorSchemeResources(android.R.color.black);
refreshLayout.setOnRefreshListener(this);
}
@Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
isFragmentVisible = menuVisible;
if (presenter != null) {
presenter.onFragmentActivated(menuVisible);
}
}
@Override
public void updateAdapterList(List<ExamsSubItem> headerItems) {
adapter.updateDataSet(headerItems);
}
@Override
public void onRefresh() {
presenter.onRefresh();
}
@Override
public void onRefreshSuccess() {
onError(R.string.sync_completed);
}
@Override
public void hideRefreshingBar() {
refreshLayout.setRefreshing(false);
}
@Override
public void showNoItem(boolean show) {
noItemView.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
}
@Override
public void showProgressBar(boolean show) {
progressBar.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
}
@Override
public void onError(String message) {
if (getActivity() != null) {
Snackbar.make(getActivity().findViewById(R.id.main_activity_view_pager),
message, Snackbar.LENGTH_LONG).show();
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
presenter.onDestroy();
}
}

View File

@ -0,0 +1,162 @@
package io.github.wulkanowy.ui.main.exams;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import io.github.wulkanowy.data.RepositoryContract;
import io.github.wulkanowy.data.db.dao.entities.Day;
import io.github.wulkanowy.data.db.dao.entities.Exam;
import io.github.wulkanowy.data.db.dao.entities.Week;
import io.github.wulkanowy.ui.base.BasePresenter;
import io.github.wulkanowy.utils.async.AbstractTask;
import io.github.wulkanowy.utils.async.AsyncListeners;
public class ExamsTabPresenter extends BasePresenter<ExamsTabContract.View>
implements ExamsTabContract.Presenter, AsyncListeners.OnFirstLoadingListener,
AsyncListeners.OnRefreshListener {
private AbstractTask refreshTask;
private AbstractTask loadingTask;
private List<ExamsSubItem> subItems = new ArrayList<>();
private String date;
private boolean isFirstSight = false;
@Inject
public ExamsTabPresenter(RepositoryContract repository) {
super(repository);
}
@Override
public void onStart(ExamsTabContract.View view) {
super.onStart(view);
getView().showProgressBar(true);
getView().showNoItem(false);
}
@Override
public void onFragmentActivated(boolean isSelected) {
if (!isFirstSight && isSelected && isViewAttached()) {
isFirstSight = true;
loadingTask = new AbstractTask();
loadingTask.setOnFirstLoadingListener(this);
loadingTask.execute();
} else if (!isSelected) {
cancelAsyncTasks();
}
}
@Override
public void setArgumentDate(String date) {
this.date = date;
}
@Override
public void onRefresh() {
if (getView().isNetworkConnected()) {
refreshTask = new AbstractTask();
refreshTask.setOnRefreshListener(this);
refreshTask.execute();
} else {
getView().onNoNetworkError();
getView().hideRefreshingBar();
}
}
@Override
public void onDoInBackgroundRefresh() throws Exception {
syncData();
}
@Override
public void onCanceledRefreshAsync() {
if (isViewAttached()) {
getView().hideRefreshingBar();
}
}
@Override
public void onEndRefreshAsync(boolean result, Exception exception) {
if (result) {
loadingTask = new AbstractTask();
loadingTask.setOnFirstLoadingListener(this);
loadingTask.execute();
getView().onRefreshSuccess();
} else {
getView().onError(getRepository().getResRepo().getErrorLoginMessage(exception));
}
getView().hideRefreshingBar();
}
@Override
public void onDoInBackgroundLoading() throws Exception {
Week week = getRepository().getDbRepo().getWeek(date);
if (week == null || !week.getExamsSynced()) {
syncData();
week = getRepository().getDbRepo().getWeek(date);
}
week.resetDayList();
List<Day> dayList = week.getDayList();
subItems = new ArrayList<>();
for (Day day : dayList) {
day.resetExams();
ExamsHeaderItem headerItem = new ExamsHeaderItem(day);
List<Exam> examList = day.getExams();
for (Exam exam : examList) {
subItems.add(new ExamsSubItem(headerItem, exam));
}
}
}
@Override
public void onCanceledLoadingAsync() {
// do nothing
}
@Override
public void onEndLoadingAsync(boolean result, Exception exception) {
if (subItems.isEmpty()) {
getView().showNoItem(true);
getView().updateAdapterList(null);
} else {
getView().updateAdapterList(subItems);
getView().showNoItem(false);
}
getView().showProgressBar(false);
}
private void syncData() throws Exception {
getRepository().getSyncRepo().syncExams(0, date);
}
private void cancelAsyncTasks() {
if (refreshTask != null) {
refreshTask.cancel(true);
refreshTask = null;
}
if (loadingTask != null) {
loadingTask.cancel(true);
loadingTask = null;
}
}
@Override
public void onDestroy() {
isFirstSight = false;
cancelAsyncTasks();
super.onDestroy();
}
}

View File

@ -1,9 +1,8 @@
package io.github.wulkanowy.ui.main.timetable;
import io.github.wulkanowy.di.annotations.PerActivity;
import io.github.wulkanowy.di.annotations.PerFragment;
import io.github.wulkanowy.ui.base.BaseContract;
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
import io.github.wulkanowy.ui.main.TabsData;
public interface TimetableContract {
@ -13,14 +12,14 @@ public interface TimetableContract {
void scrollViewPagerToPosition(int position);
void setTabDataToAdapter(TabsData tabsData);
void setTabDataToAdapter(String date);
void setAdapterWithTabLayout();
boolean isMenuVisible();
}
@PerActivity
@PerFragment
interface Presenter extends BaseContract.Presenter<View> {
void onFragmentActivated(boolean isVisible);

View File

@ -17,8 +17,8 @@ import butterknife.ButterKnife;
import io.github.wulkanowy.R;
import io.github.wulkanowy.di.component.FragmentComponent;
import io.github.wulkanowy.ui.base.BaseFragment;
import io.github.wulkanowy.ui.base.BasePagerAdapter;
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
import io.github.wulkanowy.ui.main.TabsData;
public class TimetableFragment extends BaseFragment implements TimetableContract.View {
@ -31,7 +31,7 @@ public class TimetableFragment extends BaseFragment implements TimetableContract
TabLayout tabLayout;
@Inject
TimetablePagerAdapter pagerAdapter;
BasePagerAdapter pagerAdapter;
@Inject
TimetableContract.Presenter presenter;
@ -63,8 +63,8 @@ public class TimetableFragment extends BaseFragment implements TimetableContract
}
@Override
public void setTabDataToAdapter(TabsData tabsData) {
pagerAdapter.setTabsData(tabsData);
public void setTabDataToAdapter(String date) {
pagerAdapter.addFragment(TimetableTabFragment.newInstance(date), date);
}
@Override

View File

@ -1,38 +0,0 @@
package io.github.wulkanowy.ui.main.timetable;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import io.github.wulkanowy.ui.main.TabsData;
public class TimetablePagerAdapter extends FragmentStatePagerAdapter {
private TabsData tabsData;
public TimetablePagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
void setTabsData(TabsData tabsData) {
this.tabsData = tabsData;
}
@Override
public Fragment getItem(int position) {
return tabsData.getFragment(position);
}
@Override
public int getCount() {
return tabsData.getFragmentsCount();
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return tabsData.getTitle(position);
}
}

View File

@ -8,7 +8,6 @@ import javax.inject.Inject;
import io.github.wulkanowy.data.RepositoryContract;
import io.github.wulkanowy.ui.base.BasePresenter;
import io.github.wulkanowy.ui.main.OnFragmentIsReadyListener;
import io.github.wulkanowy.ui.main.TabsData;
import io.github.wulkanowy.utils.TimeUtils;
import io.github.wulkanowy.utils.async.AbstractTask;
import io.github.wulkanowy.utils.async.AsyncListeners;
@ -20,8 +19,6 @@ public class TimetablePresenter extends BasePresenter<TimetableContract.View>
private List<String> dates = new ArrayList<>();
private TabsData tabsData = new TabsData();
private OnFragmentIsReadyListener listener;
private int positionToScroll = 0;
@ -69,8 +66,7 @@ public class TimetablePresenter extends BasePresenter<TimetableContract.View>
@Override
public void onDoInBackgroundLoading() throws Exception {
for (String date : dates) {
tabsData.addTitle(date);
tabsData.addFragment(TimetableTabFragment.newInstance(date));
getView().setTabDataToAdapter(date);
}
}
@ -82,7 +78,6 @@ public class TimetablePresenter extends BasePresenter<TimetableContract.View>
@Override
public void onEndLoadingAsync(boolean result, Exception exception) {
if (result) {
getView().setTabDataToAdapter(tabsData);
getView().setAdapterWithTabLayout();
getView().scrollViewPagerToPosition(positionToScroll);
listener.onFragmentIsReady();

View File

@ -102,6 +102,7 @@ public class TimetableTabPresenter extends BasePresenter<TimetableTabContract.Vi
week = getRepository().getDbRepo().getWeek(date);
}
week.resetDayList();
List<Day> dayList = week.getDayList();
headerItems = new ArrayList<>();

View File

@ -7,6 +7,7 @@ import java.util.List;
import io.github.wulkanowy.data.db.dao.entities.AttendanceLesson;
import io.github.wulkanowy.data.db.dao.entities.Day;
import io.github.wulkanowy.data.db.dao.entities.Diary;
import io.github.wulkanowy.data.db.dao.entities.Exam;
import io.github.wulkanowy.data.db.dao.entities.Grade;
import io.github.wulkanowy.data.db.dao.entities.Semester;
import io.github.wulkanowy.data.db.dao.entities.Student;
@ -103,6 +104,12 @@ public final class DataObjectConverter {
}
public static Day dayToDayEntity(io.github.wulkanowy.api.generic.Day day) {
return new Day()
.setDate(day.getDate())
.setDayName(day.getDayName());
}
public static Day timetableDayToDayEntity(io.github.wulkanowy.api.timetable.TimetableDay day) {
return new Day()
.setDate(day.getDate())
.setDayName(day.getDayName())
@ -123,52 +130,57 @@ public final class DataObjectConverter {
List<TimetableLesson> lessonEntityList = new ArrayList<>();
for (io.github.wulkanowy.api.generic.Lesson lesson : lessonList) {
lessonEntityList.add(lessonToTimetableLessonEntity(lesson));
lessonEntityList.add(new TimetableLesson()
.setNumber(lesson.getNumber())
.setSubject(lesson.getSubject())
.setTeacher(lesson.getTeacher())
.setRoom(lesson.getRoom())
.setDescription(lesson.getDescription())
.setGroup(lesson.getGroupName())
.setStartTime(lesson.getStartTime())
.setEndTime(lesson.getEndTime())
.setDate(lesson.getDate())
.setEmpty(lesson.isEmpty())
.setDivisionIntoGroups(lesson.isDivisionIntoGroups())
.setPlanning(lesson.isPlanning())
.setRealized(lesson.isRealized())
.setMovedOrCanceled(lesson.isMovedOrCanceled())
.setNewMovedInOrChanged(lesson.isNewMovedInOrChanged()));
}
return lessonEntityList;
}
private static TimetableLesson lessonToTimetableLessonEntity(io.github.wulkanowy.api.generic.Lesson lesson) {
return new TimetableLesson()
.setNumber(lesson.getNumber())
.setSubject(lesson.getSubject())
.setTeacher(lesson.getTeacher())
.setRoom(lesson.getRoom())
.setDescription(lesson.getDescription())
.setGroup(lesson.getGroupName())
.setStartTime(lesson.getStartTime())
.setEndTime(lesson.getEndTime())
.setDate(lesson.getDate())
.setEmpty(lesson.isEmpty())
.setDivisionIntoGroups(lesson.isDivisionIntoGroups())
.setPlanning(lesson.isPlanning())
.setRealized(lesson.isRealized())
.setMovedOrCanceled(lesson.isMovedOrCanceled())
.setNewMovedInOrChanged(lesson.isNewMovedInOrChanged());
}
public static List<AttendanceLesson> lessonsToAttendanceLessonsEntities(List<io.github.wulkanowy.api.generic.Lesson> lessonList) {
List<AttendanceLesson> lessonEntityList = new ArrayList<>();
for (io.github.wulkanowy.api.generic.Lesson lesson : lessonList) {
lessonEntityList.add(lessonToAttendanceLessonEntity(lesson));
lessonEntityList.add(new AttendanceLesson()
.setNumber(Integer.valueOf(lesson.getNumber()))
.setSubject(lesson.getSubject())
.setDate(lesson.getDate())
.setPresence(lesson.isPresence())
.setAbsenceUnexcused(lesson.isAbsenceUnexcused())
.setAbsenceExcused(lesson.isAbsenceExcused())
.setUnexcusedLateness(lesson.isUnexcusedLateness())
.setAbsenceForSchoolReasons(lesson.isAbsenceForSchoolReasons())
.setExcusedLateness(lesson.isExcusedLateness())
.setExemption(lesson.isExemption()));
}
return lessonEntityList;
}
private static AttendanceLesson lessonToAttendanceLessonEntity(io.github.wulkanowy.api.generic.Lesson lesson) {
return new AttendanceLesson()
.setNumber(Integer.valueOf(lesson.getNumber()))
.setSubject(lesson.getSubject())
.setDate(lesson.getDate())
.setPresence(lesson.isPresence())
.setAbsenceUnexcused(lesson.isAbsenceUnexcused())
.setAbsenceExcused(lesson.isAbsenceExcused())
.setUnexcusedLateness(lesson.isUnexcusedLateness())
.setAbsenceForSchoolReasons(lesson.isAbsenceForSchoolReasons())
.setExcusedLateness(lesson.isExcusedLateness())
.setExemption(lesson.isExemption());
public static List<Exam> examsToExamsEntitiy(List<io.github.wulkanowy.api.exams.Exam> examList) {
List<Exam> examEntityList = new ArrayList<>();
for (io.github.wulkanowy.api.exams.Exam exam : examList) {
examEntityList.add(new Exam()
.setDescription(exam.getDescription())
.setDate(exam.getEntryDate())
.setSubjectAndGroup(exam.getSubjectAndGroup())
.setTeacher(exam.getTeacher())
.setType(exam.getType()));
}
return examEntityList;
}
}

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#ffffff"
android:pathData="M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z" />
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#FFF"
android:pathData="M17,12h-5v5h5v-5zM16,1v2L8,3L8,1L6,1v2L5,3a2,2 0,0 0,-2 2v14c0,1.1 0.9,2
2,2h14a2,2 0,0 0,2 -2L21,5a2,2 0,0 0,-2 -2h-1L18,1h-2zM19,19L5,19L5,8h14v11z" />
</vector>

View File

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minWidth="300dp"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/timetable_dialog_relative_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="20dp"
android:paddingEnd="20dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingStart="20dp"
android:paddingTop="10dp"
tools:ignore="UselessParent">
<TextView
android:id="@+id/exams_dialog_details"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_gravity="start"
android:gravity="center_vertical"
android:maxLines="5"
android:minHeight="60dp"
android:minLines="2"
android:paddingTop="10dp"
android:text="@string/generic_dialog_details"
android:textIsSelectable="true"
android:textSize="20sp" />
<TextView
android:id="@+id/exams_dialog_subject"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/exams_dialog_details"
android:layout_marginTop="10dp"
android:text="@string/attendance_dialog_subject"
android:textIsSelectable="true"
android:textSize="17sp" />
<TextView
android:id="@+id/exams_dialog_subject_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/exams_dialog_subject"
android:layout_marginTop="3dp"
android:text="@string/generic_app_no_data"
android:textIsSelectable="true"
android:textSize="12sp" />
<TextView
android:id="@+id/exams_dialog_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/exams_dialog_subject_value"
android:layout_marginTop="10dp"
android:text="@string/exams_type"
android:textIsSelectable="true"
android:textSize="17sp" />
<TextView
android:id="@+id/exams_dialog_type_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/exams_dialog_type"
android:layout_marginTop="3dp"
android:text="@string/generic_app_no_data"
android:textIsSelectable="true"
android:textSize="12sp" />
<TextView
android:id="@+id/exams_dialog_teacher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/exams_dialog_type_value"
android:layout_marginTop="10dp"
android:text="@string/generic_dialog_teacher"
android:textSize="17sp" />
<TextView
android:id="@+id/exams_dialog_teacher_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/exams_dialog_teacher"
android:layout_marginTop="3dp"
android:text="@string/generic_app_no_data"
android:textIsSelectable="true"
android:textSize="12sp" />
<TextView
android:id="@+id/exams_dialog_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/exams_dialog_teacher_value"
android:layout_marginTop="10dp"
android:text="@string/dialog_date_text"
android:textSize="17sp" />
<TextView
android:id="@+id/exams_dialog_date_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/exams_dialog_date"
android:layout_marginTop="3dp"
android:text="@string/generic_app_no_data"
android:textIsSelectable="true"
android:textSize="12sp" />
<TextView
android:id="@+id/exams_dialog_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/exams_dialog_date_value"
android:layout_marginTop="10dp"
android:text="@string/dialog_description_text"
android:textSize="17sp" />
<TextView
android:id="@+id/exams_dialog_description_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/exams_dialog_description"
android:layout_marginTop="3dp"
android:text="@string/generic_app_no_data"
android:textIsSelectable="true"
android:textSize="12sp" />
<Button
android:id="@+id/exams_dialog_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignTop="@+id/exams_dialog_description_value"
android:layout_marginTop="25dp"
android:background="?attr/selectableItemBackground"
android:focusable="true"
android:text="@string/generic_dialog_close"
android:textAllCaps="true"
android:textSize="15sp" />
</RelativeLayout>
</LinearLayout>
</ScrollView>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#EEE"
android:minHeight="40dp"
android:paddingBottom="10dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="10dp">
<TextView
android:id="@+id/exams_header_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="@string/app_name"
android:textSize="18sp" />
<TextView
android:id="@+id/exams_header_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:layout_toEndOf="@id/exams_header_name"
android:layout_toRightOf="@id/exams_header_name"
android:gravity="end"
android:text="@string/app_name"
android:textSize="13sp" />
</RelativeLayout>

View File

@ -0,0 +1,56 @@
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/exams_subitem_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="60dp"
card_view:cardElevation="0dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/ic_border"
android:foreground="?attr/selectableItemBackgroundBorderless">
<TextView
android:id="@+id/exams_subitem_subject"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:text="@string/app_name"
android:textSize="15sp" />
<TextView
android:id="@+id/exams_subitems_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/exams_subitem_subject"
android:layout_alignStart="@id/exams_subitem_subject"
android:layout_below="@id/exams_subitem_subject"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:text="@string/app_name"
android:textSize="13sp" />
<TextView
android:id="@+id/exams_subitems_teacher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_below="@id/exams_subitem_subject"
android:layout_marginBottom="10dp"
android:layout_marginEnd="20dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="20dp"
android:layout_marginStart="10dp"
android:layout_marginTop="5dp"
android:layout_toEndOf="@id/exams_subitems_type"
android:layout_toRightOf="@id/exams_subitems_type"
android:gravity="end"
android:text="@string/app_name"
android:textSize="13sp" />
</RelativeLayout>
</android.support.v7.widget.CardView>

View File

@ -1,36 +0,0 @@
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="io.github.wulkanowy.ui.main.dashboard.DashboardFragment">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<ImageView
android:id="@+id/wrench_under_construction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView3"
android:layout_centerHorizontal="true"
android:layout_marginTop="45dp"
android:contentDescription="@string/activity_dashboard_text"
android:minHeight="100dp"
android:minWidth="100dp"
app:srcCompat="@drawable/ic_wrench_24dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="47dp"
android:text="@string/activity_under_construction"
android:textSize="17sp"
android:gravity="center"
android:textAlignment="center"
android:id="@+id/textView3" />
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>

View File

@ -0,0 +1,25 @@
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/exams_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TabLayout
android:id="@+id/exams_fragment_tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMinWidth="125dp"
app:tabMode="scrollable" />
<android.support.v4.view.ViewPager
android:id="@+id/exams_fragment_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/exams_fragment_tab_layout" />
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>

View File

@ -0,0 +1,64 @@
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/exams_tab_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="io.github.wulkanowy.ui.main.grades.GradesFragment">
<RelativeLayout
android:id="@+id/exams_tab_fragment_progress_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/exams_tab_fragment_no_item_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<ImageView
android:id="@+id/exams_tab_fragment_no_item_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/exams_tab_fragment_no_item_text"
android:layout_centerHorizontal="true"
android:layout_marginTop="40dp"
android:minHeight="100dp"
android:minWidth="100dp"
android:tint="@android:color/black"
app:srcCompat="@drawable/ic_menu_exams_24dp"
tools:ignore="contentDescription" />
<TextView
android:id="@+id/exams_tab_fragment_no_item_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="46dp"
android:text="@string/exams_no_entries"
android:textAlignment="center"
android:textSize="20sp" />
</RelativeLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/exams_tab_fragment_swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/exams_tab_fragment_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
</android.support.design.widget.CoordinatorLayout>

View File

@ -30,7 +30,7 @@
<string name="noColor_text">Brak koloru</string>
<string name="activity_dashboard_text">Aktywność dashboard</string>
<string name="dashboard_text">Dashboard</string>
<string name="exams_text">Exams</string>
<string name="grades_text">Oceny</string>
<string name="attendance_text">Frekwencja</string>
<string name="timetable_text">Plan lekcji</string>
@ -139,4 +139,6 @@
<string name="widget_timetable_no_lesson">Brak lekcji</string>
<string name="widget_timetable_today">Dziś</string>
<string name="widget_timetable_tomorrow">Jutro</string>
<string name="exams_no_entries">Brak sprawdzianów w tym tygodniu</string>
<string name="exams_type">Typ</string>
</resources>

View File

@ -3,7 +3,7 @@
<string-array name="startup_tab_entries" translatable="false">
<item>@string/grades_text</item>
<item>@string/attendance_text</item>
<item>@string/dashboard_text</item>
<item>@string/exams_text</item>
<item>@string/timetable_text</item>
</string-array>
<string-array name="startup_tab_value" translatable="false">

View File

@ -30,7 +30,7 @@
<string name="noColor_text">No color</string>
<string name="activity_dashboard_text">Dashboard Activity</string>
<string name="dashboard_text">Dashboard</string>
<string name="exams_text">Exams</string>
<string name="grades_text">Grades</string>
<string name="attendance_text">Attendance</string>
<string name="timetable_text">Timetable</string>
@ -134,4 +134,6 @@
<string name="widget_timetable_no_lesson">No lessons</string>
<string name="widget_timetable_today">Today</string>
<string name="widget_timetable_tomorrow">Tomorrow</string>
<string name="exams_no_entries">No exams in this week</string>
<string name="exams_type">Type</string>
</resources>