In this guide we will set you up and teach you how to contribute.
- We recommend using WebStorm which you can find here. Otherwise Visual Studio Code works fine. You'll need something that you can write TypeScript code comfortably in.
- You should have the API set up before you set up the frontend. Find that here.
- Get a business token from the backend MySQL database.
-
Clone the dev branch by running,
git clone https://github.com/gigwerk-io/cookie-pwa.git
-
Create a new branch for your ticket from develop with the ticket's name,
git checkout -b GIGWERK-{your ticket number}
-
Install ionic globally
npm install -g @ionic/cli
-
Install tailwindcss angular cli
npm i ng-tailwindcss -g
-
Run
npm install
-
Change the
apiUrl
in./environments/environment.ts
by providing it with a valid Business Token acquired from the backend MySQL database. Should look something like this,export const environment = { production: false, apiRootUrl: 'http://local.gigwerk.io', apiUrl: http://local.gigwerk.io/business/{business token here} };
-
Run
npm run start
- For UI Components we use Tailwind UI. Virtually all of our css needs are handled by this utility. You will likely never write css code on this project if you learn how to use it. Learn more here
- For UI icons used in buttons and elsewhere this project uses a Flaticons UI interface pack. Most of them are already downloaded but if you find that one you need isn't in
./src/assets/icon/interface/*.svg
go here to find them. Make sure to download svg only - For 'artsy' iconography we use Undraw as our design solution. Find that here. Make sure to set the color of the Undraw images to #3AC23E before downloading them into the project. These Undraw images are located in
./src/assets/undraw
. - Never hurts to learn some Angular, Capacitor and RxJS either as these are always going to be in use. On a lesser extent we are lightly using the Ionic Framework. Lightly! we don't want to use almost any of their components. However, if you're in a pinch you may be able to get away with using something lowkey like an Ion List or Ion Item. Beware we will most likely have custom built components already for almost all of our needs so any usage is strictly temporary.
- We will use the camelCase naming convention for variable naming.
- When you're programming prefer to use Dynamic Programming wherever you encounter a problem that could be solved best with it. You should also prefer using Functional Programming (Declaritive) techniques over Imperative Programming (traditional).
someVariable = undefined; // This variable has some assumed type
someVariable: someType = undefined; // This is for all types even any. We want to know what this variable's type is because not everyone might have their IDE set up to see the type generated
public foo()
{
this.myFooLogic();
}
public foo(): someType {
this.myFooLogic();
}
public constructor(public router: Router) {
}
We should refrain from using the angular router as it does not provide page transition animations out of the box like the ionic nav controller this is one of the few things we would use from ionic.
public constructor(public navCtrl: NavController) {
}
- If you're trying to build something really complicated to do something simple, check to see if it's already been built or there's something in the code that can help make that thing you're making.
- Use the
alertService
to alert the user with some useful message. The API is already built in and there's a few examples in the codebase already.
For event handling on the frontend we use the events service to help with communicating data between multiple components and services. It uses the Observables/Promise design pattern.
export class ListenerComponent implements OnInit, OnDestroy {
constructor(
public events: Events
) {
}
ngOnInit() {
this.events.subscribe('topic', (data: DataType) => foo(data)); // listen to updates
}
ngOnDestroy() {
this.events.unsubscribe('topic'); // clean up so there's no memory leaks!
}
}
export class PublisherComponent {
constructor(
public events: Events
) {
this.events.publish('topic', data);
}
}
reportAbuse() {
this.alertService.show({
alertMessage: 'Thank you for submitting this report! We will look into it as soon as possible.',
color: 'blue',
position: 'top-0',
enterAnimation: 'top-slidedown',
leaveAnimation: 'top-slideup',
duration: 4000
})
}
With the modal service you have to create a content component to display within the modal first. We recommend you just slot it in right under the page component it'll appear in to keep things organized. Something like this.
@Component({
selector: 'gig-some-modal',
template: `
<div (click)="dismissModal()">Hello world!</div>
`,
styleUrls: ['some.page.scss']
})
export class SomeModal implements ModalContentComponent {
modalOptions: ModalOptions;
constructor(
public modalService: ModalService
) {}
dismissModal() {
this.modalService.dismiss();
}
}
Then you've got to use this component in the parent class component it lives in.
export class SomeParentComponent {
constructor(
public modalService: ModalService
) {}
openSomeModal() {
this.modalService.show({
position: 'middle',
component: SomeModal
});
}
}
The announcement service is used to tell the user when a request isn't fullfilled. Think http errors. Announcement service should be called primarily in a http service class.
public withdrawProposal(jobId: number): Promise<Response<null>> {
return this.makeHttpRequest<Response<null>>(`marketplace/job/${jobId}/withdraw`, 'POST')
.then(httpRes => httpRes.toPromise())
.catch((e: HttpErrorResponse) => {
console.log(e.status);
this.announcementService.show({
message: 'Something went wrong with this request.',
color: 'red'
});
return undefined;
});
}