Skip to content

Commit

Permalink
Merge pull request #12 from piuswalter/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
piuswalter authored Apr 19, 2021
2 parents 74ffe69 + 5550183 commit 78f5695
Show file tree
Hide file tree
Showing 67 changed files with 613 additions and 441 deletions.
52 changes: 51 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,51 @@
# StudyOffline
<div align="center">
<a href="#"><img src="https://raw.githubusercontent.com/piuswalter/StudyOffline/main/logo.png" alt="StudyOffline" width="200"></a>
<br />
<h1>StudyOffline</h1>
<small>Built with ❤️ and 🍺 by
<a href="https://github.com/p-fruck">Philipp</a>,
<a href="https://github.com/piuswalter">Pius</a> and
<a href="https://github.com/piuswalter/StudyOffline/graphs/contributors">contributors</a>
</small>
</div>

---

[![GitHub license](https://img.shields.io/github/license/piuswalter/StudyOffline)](https://github.com/piuswalter/StudyOffline/blob/main/LICENSE.md)
![GitHub last commit (branch)](https://img.shields.io/github/last-commit/piuswalter/StudyOffline/development)
[![GitHub issues](https://img.shields.io/github/issues/piuswalter/StudyOffline)](https://github.com/piuswalter/StudyOffline/issues)
![Lines of code](https://img.shields.io/tokei/lines/github/piuswalter/StudyOffline)
![GitHub language count](https://img.shields.io/github/languages/count/piuswalter/StudyOffline)

StudyOffline is an open source tool that allows you to download the flashcards you have created on StudySmarter and study them offline.

In addition, StudyOffline is a PWA (Progressive Web App) with which you can also learn your flashcards on any smartphone.

## ⚒️ Setup your own StudyOffline instance

[![Deploy with Docker](https://img.shields.io/badge/deploy%20with-docker-0db7ed)]()

At the moment we do not have published StudyOffline to any container registry yet but you can easily build it by hand.

The requirement is that Docker is installed.

To do this, you just need to run

`docker build https://github.com/piuswalter/StudyOffline.git#main -t studyoffline --no-cache`

Now your container is built and can be started with

`docker run -p 3000:3000 --name studyoffline -d studyoffline`

You can access StudyOffline in your browser on `https://localhost:3000/`.

## ⚙️ Built with latest technologies

- [Express](https://expressjs.com/) - The web framework used at the backend
- [Angular](https://angular.io/) - The web framework used at the frontend
- [Node.js](https://nodejs.org/en/) - The backend power
- [IndexedDB](https://developer.mozilla.org/de/docs/Web/API/IndexedDB_API) - The database to store your flashcards

## 📜 License

This project is licensed under the AGPL-3.0 License - see the [LICENSE.md](LICENSE.md) file for details
5 changes: 3 additions & 2 deletions backend/src/utils/encoder.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ export default class FlashcardEncoder extends Readable {

// eslint-disable-next-line class-methods-use-this
async encodeFromURL(imageURL: string): Promise<string> {
const { data } = await Axios.get(imageURL);
return Buffer.from(data, 'binary').toString('base64');
const { data, headers } = await Axios.get(imageURL, { responseType: 'arraybuffer' });
const prefix = `data:${headers['content-type']};base64, `;
return prefix + Buffer.from(data, 'binary').toString('base64');
}
}
3 changes: 2 additions & 1 deletion frontend/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"root": true,
"ignorePatterns": [
"projects/**/*"
"projects/**/*",
"*.spec.ts"
],
"overrides": [
{
Expand Down
4 changes: 2 additions & 2 deletions frontend/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/favicon.ico",
"src/favicon.png",
"src/assets",
"src/manifest.webmanifest"
],
Expand Down Expand Up @@ -95,7 +95,7 @@
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/favicon.png",
"src/assets",
"src/manifest.webmanifest"
],
Expand Down
2 changes: 1 addition & 1 deletion frontend/ngsw-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"installMode": "prefetch",
"resources": {
"files": [
"/favicon.ico",
"/favicon.png",
"/index.html",
"/manifest.webmanifest",
"/*.css",
Expand Down
8 changes: 7 additions & 1 deletion frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"build": "ng build --prod",
"test": "ng test",
"lint": "eslint \"./src/**/*.{js,ts}\" --quiet --fix",
"e2e": "ng e2e"
Expand All @@ -22,6 +22,7 @@
"@angular/platform-browser-dynamic": "^11.0.9",
"@angular/router": "^11.0.9",
"@angular/service-worker": "^11.0.9",
"dexie": "^3.0.3",
"rxjs": "^6.6.7",
"tslib": "^2.1.0",
"zone.js": "~0.10.2"
Expand Down
33 changes: 33 additions & 0 deletions frontend/src/app/_models/flashcard.class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Origin } from './origin.enum';

export interface IAnswer {
text: string;
isCorrect: boolean;
}

interface FlashcardIndices {
id?: number;
subjectId: number;
}

export abstract class Flashcard {
id?: number;
subjectId: number;

constructor(ind: FlashcardIndices) {
this.id = ind.id;
this.subjectId = ind.subjectId;
}

abstract readonly origin: Origin;
abstract question: string;
abstract answers: IAnswer[];
abstract hints: string[];
abstract solution: string;
abstract tags: number[];

get withoutId(): Flashcard {
delete this.id;
return this;
}
}
17 changes: 0 additions & 17 deletions frontend/src/app/_models/flashcard.interface.ts

This file was deleted.

29 changes: 29 additions & 0 deletions frontend/src/app/_models/internal/flashcard.class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Flashcard, IAnswer } from '../flashcard.class';
import { Origin } from '../origin.enum';

export interface IInternalFlashcard {
id: number;
question: string;
answers: IAnswer[];
hints: string[];
solution: string;
tags: number[];
}

export class InternalFlashcard extends Flashcard {
readonly origin = Origin.internal;
question: string;
answers: IAnswer[];
hints: string[];
solution: string;
tags: number[];

constructor(flashcard: IInternalFlashcard, subjectId: number) {
super({ subjectId });
this.question = flashcard.question;
this.answers = flashcard.answers;
this.hints = flashcard.hints;
this.solution = flashcard.solution;
this.tags = flashcard.tags;
}
}
5 changes: 5 additions & 0 deletions frontend/src/app/_models/origin.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// eslint-disable-next-line no-shadow
export enum Origin {
internal,
studySmarter
}
10 changes: 0 additions & 10 deletions frontend/src/app/_models/query-catalog.interface.ts

This file was deleted.

41 changes: 41 additions & 0 deletions frontend/src/app/_models/studysmarter/flashcard.class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { IStudySmarterFlashcard } from '.';
import { Flashcard, IAnswer } from '../flashcard.class';
import { Origin } from '../origin.enum';

export class StudySmarterFlashcard extends Flashcard {
studySmarter: IStudySmarterFlashcard;
readonly origin = Origin.studySmarter;

constructor(flashcard: IStudySmarterFlashcard, subjectId: number) {
super({ subjectId });
this.studySmarter = flashcard;
}

private get flashcardinfo() {
return this.studySmarter.flashcardinfo;
}

get question(): string {
if (!this.flashcardinfo.question_html.length) return '';
return this.flashcardinfo.question_html[0].text;
}

get answers(): IAnswer[] {
return this.flashcardinfo.answer_html.map((answr) => ({
text: answr.text,
isCorrect: answr.is_correct
}));
}

get hints(): string[] {
return this.flashcardinfo.hint_html;
}

get solution(): string {
return this.flashcardinfo.solution_html;
}

get tags(): number[] {
return [];
}
}
22 changes: 22 additions & 0 deletions frontend/src/app/_models/studysmarter/flashcard.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
interface StudySmarterFlashcardAnswer {
text: string;
// eslint-disable-next-line @typescript-eslint/naming-convention
is_correct: boolean;
}

export interface IStudySmarterFlashcard {
id?: number;
subjects: number[];

flashcardinfo: {
id?: number;
creator: number;
/* eslint-disable @typescript-eslint/naming-convention */
question_html: StudySmarterFlashcardAnswer[];
answer_html: StudySmarterFlashcardAnswer[];
hint_html: string[];
solution_html: string;
};
community_applied_tag_ids: number[];
/* eslint-enable @typescript-eslint/naming-convention */
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export * from './flashcard.class';
export * from './flashcard.interface';
export * from './login-request.interface';
export * from './login-response.interface';
export * from './studysmarter-response.interface';
export * from './response.interface';
export * from './subject.class';
export * from './subject.interface';
24 changes: 24 additions & 0 deletions frontend/src/app/_models/studysmarter/subject.class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { IStudySmarterSubject } from '.';
import { Flashcard } from '../flashcard.class';
import { Subject } from '../subject.class';

export class StudySmarterSubject extends Subject {
studySmarter: IStudySmarterSubject;

constructor(subject: IStudySmarterSubject, id?: number) {
super(id);
this.studySmarter = subject;
}

get name(): string {
return this.studySmarter.name;
}

get archived(): boolean {
return this.studySmarter.archived;
}

get flashcards(): Flashcard[] {
return [];
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable camelcase */
export interface Subject {
export interface IStudySmarterSubject {
id: number;
name: string;
/* eslint-disable @typescript-eslint/naming-convention */
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/app/_models/subject.class.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Flashcard } from './flashcard.class';

export abstract class Subject {
id?: number;

constructor(id?: number) {
this.id = id;
}

abstract name: string;
abstract archived: boolean;
abstract flashcards: Flashcard[];
}
Loading

0 comments on commit 78f5695

Please sign in to comment.