Skip to content

Commit

Permalink
Merge branch 'master' into model_relationship
Browse files Browse the repository at this point in the history
  • Loading branch information
DonGiovanni83 committed Nov 8, 2018
2 parents 93c226e + 055d9b2 commit 1caf54c
Show file tree
Hide file tree
Showing 15 changed files with 405 additions and 16 deletions.
1 change: 0 additions & 1 deletion backend/reset_db_and_migrate.sh
Expand Up @@ -3,7 +3,6 @@ docker-compose up -d postgres;
sleep 1;
./node_modules/.bin/ts-node ./node_modules/.bin/typeorm migration:generate -n Init;
echo "
-------------------------------------------------------------------------------------
Replace used migration InitFile in src/index.ts with the newly createt version.
-------------------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions backend/schema.graphql
Expand Up @@ -32,6 +32,7 @@ enum ApplicationState {
PENDING
DECLINED
APPROVED

}

input CreateJobInput {
Expand Down
2 changes: 2 additions & 0 deletions backend/src/graphql/resolvers/_mutations/index.ts
Expand Up @@ -10,6 +10,7 @@ import removeBookmark from "./removeBookmark";
import approve from "./approve";
import apply from "./apply";


export const Mutation: MutationResolvers.Type = {
createJob,
updateJob,
Expand All @@ -21,6 +22,7 @@ export const Mutation: MutationResolvers.Type = {
removeBookmark,
apply,
approve

};

export default Mutation;
1 change: 1 addition & 0 deletions backend/src/graphql/resolvers/_queries/jobs.test.ts
Expand Up @@ -8,6 +8,7 @@ import { OrganizationRepository } from "../../../repository/OrganizationReposito
import { UserRepository } from "../../../repository/UserRepository";
import { ApplicationRepository } from "../../../repository/ApplicationRepository";


describe("Get likedJobs", () => {
const schema = makeExecutableSchema({
typeDefs: importSchema("./schema.graphql"),
Expand Down
1 change: 1 addition & 0 deletions backend/src/index.ts
Expand Up @@ -19,6 +19,7 @@ import { Application } from "./entity/Application";
import { ApplicationRepository } from "./repository/ApplicationRepository";
import { Init1541547194885 } from "./migration/1541547194885-Init";


//TODO environment variable for logging (e.g. NODE_ENV)
createConnection({
type: "postgres",
Expand Down
47 changes: 47 additions & 0 deletions backend/src/migration/1541366395158-Init.ts
@@ -0,0 +1,47 @@
import { MigrationInterface, QueryRunner } from "typeorm";

export class Init1541366395158 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(
`CREATE TABLE "organizations" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "name" text NOT NULL, CONSTRAINT "PK_6b031fcd0863e3f6b44230163f9" PRIMARY KEY ("id"))`
);
await queryRunner.query(
`CREATE TABLE "users" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "firstname" text NOT NULL, "lastname" text NOT NULL, "phone" text NOT NULL, "email" text NOT NULL, "password" text NOT NULL, CONSTRAINT "UQ_97672ac88f789774dd47f7c8be3" UNIQUE ("email"), CONSTRAINT "PK_a3ffb1c0c8416b9fc6f907b7433" PRIMARY KEY ("id"))`
);
await queryRunner.query(
`CREATE TABLE "jobs" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "title" text NOT NULL, "description" text NOT NULL, "salary" float NOT NULL, "start" date NOT NULL, "end" TIMESTAMP, "organizationId" uuid, CONSTRAINT "PK_cf0a6c42b72fcc7f7c237def345" PRIMARY KEY ("id"))`
);
await queryRunner.query(
`CREATE TABLE "roles" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "title" text NOT NULL, "description" text NOT NULL, CONSTRAINT "PK_c1433d71a4838793a49dcad46ab" PRIMARY KEY ("id"))`
);
await queryRunner.query(
`CREATE TABLE "bookmarks" ("usersId" uuid NOT NULL, "jobsId" uuid NOT NULL, CONSTRAINT "PK_59b0563d7b6f7758e9f369bb324" PRIMARY KEY ("usersId", "jobsId"))`
);
await queryRunner.query(
`ALTER TABLE "jobs" ADD CONSTRAINT "FK_08bdc8b939f39e6d55b4c38cfb9" FOREIGN KEY ("organizationId") REFERENCES "organizations"("id")`
);
await queryRunner.query(
`ALTER TABLE "bookmarks" ADD CONSTRAINT "FK_b0075fdec79957795cd75fb7bb9" FOREIGN KEY ("usersId") REFERENCES "users"("id") ON DELETE CASCADE`
);
await queryRunner.query(
`ALTER TABLE "bookmarks" ADD CONSTRAINT "FK_4d0391697f8d396f21846c8784a" FOREIGN KEY ("jobsId") REFERENCES "jobs"("id") ON DELETE CASCADE`
);
}

public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(
`ALTER TABLE "bookmarks" DROP CONSTRAINT "FK_4d0391697f8d396f21846c8784a"`
);
await queryRunner.query(
`ALTER TABLE "bookmarks" DROP CONSTRAINT "FK_b0075fdec79957795cd75fb7bb9"`
);
await queryRunner.query(
`ALTER TABLE "jobs" DROP CONSTRAINT "FK_08bdc8b939f39e6d55b4c38cfb9"`
);
await queryRunner.query(`DROP TABLE "bookmarks"`);
await queryRunner.query(`DROP TABLE "roles"`);
await queryRunner.query(`DROP TABLE "jobs"`);
await queryRunner.query(`DROP TABLE "users"`);
await queryRunner.query(`DROP TABLE "organizations"`);
}
}
1 change: 1 addition & 0 deletions backend/src/repository/UserRepository.ts
Expand Up @@ -47,6 +47,7 @@ export class UserRepository {
}

async removeBookmark(jobId: string, session: Express.Session): Promise<any> {

Utils.enforceAuth(session);

await getConnection()
Expand Down
56 changes: 56 additions & 0 deletions frontend/components/student/StudentJobCard.tsx
@@ -0,0 +1,56 @@
import {Button, Card, Header, Loader} from "semantic-ui-react";
import * as React from "react";
import {SingletonRouter} from "next/router";
import Link from "next/link";
import ApolloError from 'apollo-boost';

interface StudentJobCardProps {
router?: SingletonRouter,
job: {
id: string,
title: string,
description: string
},
loading: boolean,
error: ApolloError;
}


const StudentJobCard: React.SFC<StudentJobCardProps> = ({router, job, loading, error}) => {

if (loading) {
return (
<Card>
<Loader/>
</Card>
);
}
if (error) {
return (
<Card>
<Header as="h3">Ooops</Header>
</Card>
);
}

return (
<Card>
<Card.Content>
<Card.Header>{job.title}</Card.Header>
<Card.Description>
{job.description}
</Card.Description>
</Card.Content>
<Card.Content extra>
<div className='ui two buttons'>
<Button icon="star"/>
<Link href={{pathname: "/jobs/detail", query: {id: job.id}}}>
<Button icon="eye"/>
</Link>
</div>
</Card.Content>
</Card>
);
};

export default StudentJobCard;
63 changes: 63 additions & 0 deletions frontend/components/student/activity/StudentActivities.tsx
@@ -0,0 +1,63 @@
import {SingletonRouter} from "next/router";
import * as React from "react";
import {Card, Header, Loader, Segment} from "semantic-ui-react";
import {ApolloError} from "apollo-boost";
import gql from "graphql-tag";
import {Query} from "react-apollo";
import StudentActivity from "./StudentActivity";
import StudentJobCard from "../StudentJobCard";


interface ActivitiesJobs {
jobs: {
id: string;
title: string;
description: string;
organization: { id: string; name };
}[];
}


interface StudentActivitiesProps {
router?: SingletonRouter;
loading: boolean;
error: ApolloError;
data: ActivitiesJobs;
}

export const GET_ACTIVITIES_JOBS = gql`
query StudentActivities {
jobs {
id
title
description
organization {
id
name
}
}
}
`;


const StudentActivities: React.SFC<StudentActivitiesProps> = ({router, loading, error, data}) => {
return (
<Segment>
<Header>My Activities</Header>
<Card.Group itemsPerRow={3} centered>
{data.jobs.map(job => (
<StudentActivity key={job.id} job={job} loading={loading} error={error}/>
))}
</Card.Group>
</Segment>
);
};


export default () => (
<Query query={GET_ACTIVITIES_JOBS}>
{({loading, error, data}) => (
<StudentActivities data={data} error={error} loading={loading}/>
)}
</Query>
);
46 changes: 46 additions & 0 deletions frontend/components/student/activity/StudentActivity.tsx
@@ -0,0 +1,46 @@
import * as React from "react";
import {Card, Header, Loader} from "semantic-ui-react";
import ApolloError from 'apollo-boost'

interface StudentActivitiesProps {
job: {
id: string,
title: string,
description: string
organisation: {
id: string,
name: string
}
},
loading: boolean,
error: ApolloError
}

const StudentActivity: React.SFC<StudentActivitiesProps> = ({job, loading, error}) => {

if (loading) {
return (
<Card>
<Loader/>
</Card>
);
}
if (error) {
return (
<Card>
<Header as="h3">Ooops</Header>
</Card>
);
}

return (
<Card>
<Card.Content>
<Card.Header>{job.title}</Card.Header>
<Card.Meta>{job.description}</Card.Meta>
</Card.Content>
</Card>
);
};

export default StudentActivity;
18 changes: 18 additions & 0 deletions frontend/components/student/dashboard/StudentDashboard.tsx
@@ -0,0 +1,18 @@
import withAuthorization from "../../Auth/withAuthorization";
import Me from "../../Auth/Me";
import * as React from "react";
import {Container} from "semantic-ui-react";
import RecommendedJobs from "../recomendedjobs/RecommendedJobs";
import StudentActivities from "../activity/StudentActivities";
import StudentWatching from "../watching/StudentWatching";

const StudentDashboard = () => (
<Container>
<Me/>
<RecommendedJobs/>
<StudentActivities/>
<StudentWatching/>
</Container>
);

export default withAuthorization(StudentDashboard);
75 changes: 75 additions & 0 deletions frontend/components/student/recomendedjobs/RecommendedJobs.tsx
@@ -0,0 +1,75 @@
import StudentJobCard from "../StudentJobCard";
import * as React from "react";
import {Query} from "react-apollo";
import gql from "graphql-tag";
import {Card, Header, Loader, Segment} from "semantic-ui-react";
import {ApolloError} from "apollo-boost";

export const GET_RECOMMENDED_JOBS = gql`
query RecommendedJobs {
jobs {
id
title
description
organization {
id
name
}
}
}
`;

interface RecommendedJobsProps {
loading: boolean;
error: ApolloError;
data: AllJobs;
}


const RecommendedJobs: React.SFC<RecommendedJobsProps> = ({loading, error, data}) => {

if (loading) {
return (
<Segment>
<Header as="h3">Recommended Jobs</Header>
<Card.Group itemsPerRow={3} centered>
<Card><Loader/></Card>
<Card><Loader/></Card>
<Card><Loader/></Card>
</Card.Group>
</Segment>
)
}

if (error) {
return (
<Segment>
<Header as="h3">Recommended Jobs</Header>
<Card.Group itemsPerRow={3} centered>
<Card><Header as="h3">Ooops</Header></Card>
<Card><Header as="h3">Ooops</Header></Card>
<Card><Header as="h3">Ooops</Header></Card>
</Card.Group>
</Segment>
)
}

return (
<Segment>
<Header as="h3">Recommended Jobs</Header>
<Card.Group itemsPerRow={3} centered>
{data.jobs.map(job => (
<StudentJobCard key={job.id} job={job}/>
))}
</Card.Group>
</Segment>
);
};

export default () => (
<Query query={GET_RECOMMENDED_JOBS}>
{({loading, error, data}) => (
<RecommendedJobs data={data} error={error} loading={loading}/>
)}
</Query>
);

0 comments on commit 1caf54c

Please sign in to comment.