Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ export const routes: Routes = [
(mod) => mod.PrivacyPolicyComponent,
),
},
{
path: 'my-projects',
loadComponent: () =>
import('./features/my-projects/my-projects.component').then(
(mod) => mod.MyProjectsComponent,
),
},
{
path: 'settings',
loadChildren: () =>
Expand Down
2 changes: 1 addition & 1 deletion src/app/core/components/nav-menu/nav-menu.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: item.useExactMatch }"
class="nav-link flex"
[class.mt-5]="item.label === 'Settings'"
[class.mt-5]="item.label === 'Settings' || item.label === 'My Projects'"
>
@if (item.icon) {
<i [class]="item.icon" class="nav-icon"></i>
Expand Down
6 changes: 6 additions & 0 deletions src/app/core/helpers/nav-items.constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ export const NAV_ITEMS: NavItem[] = [
icon: 'support',
useExactMatch: true,
},
{
path: '/my-projects',
label: 'My Projects',
icon: 'my-projects',
useExactMatch: true,
},
{
path: '/settings',
label: 'Settings',
Expand Down
39 changes: 14 additions & 25 deletions src/app/core/services/json-api/json-api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,25 @@ export class JsonApiService {
http: HttpClient = inject(HttpClient);

get<T>(url: string, params?: Record<string, unknown>): Observable<T> {
let httpParams = new HttpParams();

if (params) {
for (const key in params) {
const value = params[key];
return this.http
.get<JsonApiResponse<T>>(url, { params: this.buildHttpParams(params) })
.pipe(map((response) => response.data));
}

if (Array.isArray(value)) {
value.forEach((item) => {
httpParams = httpParams.append(`${key}[]`, item); // Handles arrays
});
} else {
httpParams = httpParams.set(key, value as string);
}
}
}
getArray<T>(url: string, params?: Record<string, unknown>): Observable<T[]> {
const headers = new HttpHeaders({
Authorization: 'ENTER_VALID_PAT',
});

return this.http
.get<JsonApiResponse<T>>(url)
.get<JsonApiArrayResponse<T>>(url, {
params: this.buildHttpParams(params),
headers: headers,
})
.pipe(map((response) => response.data));
}

getArray<T>(url: string, params?: Record<string, unknown>): Observable<T[]> {
private buildHttpParams(params?: Record<string, unknown>): HttpParams {
let httpParams = new HttpParams();

if (params) {
Expand All @@ -51,14 +48,6 @@ export class JsonApiService {
}
}

const headers = new HttpHeaders({
Authorization: `Bearer UlO9O9GNKgVzJD7pUeY53jiQTKJ4U2znXVWNvh0KZQruoENuILx0IIYf9LoDz7Duq72EIm`,
});

return this.http
.get<
JsonApiArrayResponse<T>
>(url, { params: httpParams, headers: headers })
.pipe(map((response) => response.data));
return httpParams;
}
}
2 changes: 1 addition & 1 deletion src/app/features/home/dashboard.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class DashboardService {
jsonApiService = inject(JsonApiService);

getProjects(): Observable<Project[]> {
const userId = 'k9p2t';
const userId = 'ENTER_VALID_USER_ID';
const params = {
embed: ['bibliographic_contributors', 'parent', 'root'],
page: 1,
Expand Down
2 changes: 1 addition & 1 deletion src/app/features/home/home.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

.quick-search-container {
background: white;
padding: 1.71rem;
padding: 2rem;

.text-center {
font-size: 1rem;
Expand Down
7 changes: 4 additions & 3 deletions src/app/features/home/home.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ import {
styleUrl: './home.component.scss',
})
export class HomeComponent implements OnInit {
isMedium = toSignal(inject(IS_MEDIUM));
isMobile = toSignal(inject(IS_XSMALL));
dashboardService: DashboardService = inject(DashboardService);
#store = inject(Store);
protected readonly isMedium = toSignal(inject(IS_MEDIUM));
protected readonly isMobile = toSignal(inject(IS_XSMALL));
protected readonly dashboardService: DashboardService =
inject(DashboardService);

protected readonly projects = this.#store.selectSignal(
HomeSelectors.getProjects,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<form
[formGroup]="projectForm"
(ngSubmit)="submitForm()"
class="flex flex-column gap-4"
>
<!-- Title -->
<div class="flex flex-column">
<label for="project-title">Title</label>
<input
pInputText
id="project-title"
type="text"
[formControlName]="ProjectFormControls.Title"
/>
</div>

<!-- Storage Location -->
<div class="flex flex-column">
<label for="storage-location">Storage Location</label>
<p-select
id="storage-location"
[options]="storageLocations"
[formControlName]="ProjectFormControls.StorageLocation"
></p-select>
</div>

<!-- Affiliations -->
<div class="flex flex-column gap-2">
<div class="relative">
<h3 class="font-normal mb-2">Affiliation</h3>
<div class="flex gap-4 absolute top-0 right-0">
<p-button
class="secondary-transparent"
type="button"
severity="secondary"
(click)="selectAllAffiliations()"
(keydown.enter)="selectAllAffiliations()"
>
Select All
</p-button>
<p-button
class="secondary-transparent"
type="button"
severity="secondary"
(click)="removeAllAffiliations()"
(keydown.enter)="removeAllAffiliations()"
>
Remove All
</p-button>
</div>
</div>

<div class="flex gap-2" role="group" aria-label="Affiliations">
@for (affiliation of affiliations; track affiliation.value) {
<div class="flex align-items-center relative gap-2">
<p-checkbox
class="absolute top-0 affiliation-checkbox"
[value]="affiliation.value"
[formControlName]="ProjectFormControls.Affiliations"
[inputId]="affiliation.value"
/>
<img
ngSrc="assets/images/сos-shield.svg"
alt="OSF Logo"
height="44"
width="44"
/>
</div>
}
</div>
</div>

<!-- Description -->
<div class="flex flex-column">
<label for="description">Description (Optional)</label>
<textarea
pTextarea
id="description"
[formControlName]="ProjectFormControls.Description"
[rows]="5"
></textarea>
</div>

<!-- Template -->
<div class="flex flex-column">
<label for="template">Template (Optional)</label>
<p-select
id="template"
[options]="projectTemplateOptions()"
[formControlName]="ProjectFormControls.Template"
[placeholder]="'Select template or start typing to find one'"
[filter]="true"
styleClass="w-full"
appendTo="body"
[showClear]="hasTemplateSelected()"
></p-select>
</div>

<!-- Actions -->
<div class="flex justify-content-end gap-2">
<p-button
class="w-12rem btn-full-width"
label="Cancel"
severity="info"
(click)="dialogRef.close()"
/>
<p-button
class="w-12rem btn-full-width"
label="Create Project"
type="submit"
[disabled]="!projectForm.valid"
/>
</div>
</form>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@use "assets/styles/variables" as var;

:host {
label {
color: var.$dark-blue-1;
}

h3 {
text-transform: none;
color: var.$dark-blue-1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { AddProjectFormComponent } from './add-project-form.component';

describe('AddProjectFormComponent', () => {
let component: AddProjectFormComponent;
let fixture: ComponentFixture<AddProjectFormComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AddProjectFormComponent],
}).compileComponents();

fixture = TestBed.createComponent(AddProjectFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Loading