Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • web-et-numerique/factory/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_client
1 result
Show changes
Commits on Source (10)
Showing
with 496 additions and 1294 deletions
.angular/
.git/
.idea/
.vscode/
build/
coverage/
dist/
node_modules/
\ No newline at end of file
{
"root": true,
"ignorePatterns": ["projects/**/*"],
"overrides": [
{
"files": ["*.ts"],
"parserOptions": {
"project": ["tsconfig.json"],
"createDefaultProgram": true
},
"extends": ["plugin:@angular-eslint/recommended", "plugin:@angular-eslint/template/process-inline-templates"],
"rules": {
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "app",
"style": "camelCase"
}
],
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "app",
"style": "kebab-case"
}
]
}
},
{
"files": ["*.html"],
"extends": ["plugin:@angular-eslint/template/recommended"],
"rules": {}
}
]
}
......@@ -54,5 +54,9 @@ api/db.json
# Documentation generated with compodoc
documentation
CHANGELOG.md
package-lock.json
# External libs
/projects
{
"printWidth": 128,
"tabWidth": 2,
"printWidth": 120,
"singleQuote": true,
"useTabs": false,
"tabWidth": 2,
"semi": true,
"singleQuote": true,
"quoteProps": "as-needed",
"jsxSingleQuote": true,
"trailingComma": "none",
"bracketSpacing": true,
"bracketSameLine": true,
"arrowParens": "always",
"requirePragma": false,
"insertPragma": false,
"proseWrap": "preserve",
"htmlWhitespaceSensitivity": "ignore",
"vueIndentScriptAndStyle": false,
"endOfLine": "lf",
"embeddedLanguageFormatting": "auto"
"bracketSpacing": true
}
......@@ -15,7 +15,6 @@ RUN npm install --silent
COPY angular.json .
COPY tsconfig.json .
COPY tsconfig.app.json .
COPY tsconfig.base.json .
COPY ngsw-config.json .
COPY /nginx/nginx.conf .
COPY /src ./src
......
......@@ -35,10 +35,7 @@
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"localize": true,
"allowedCommonJsDependencies": [
"lodash",
"leaflet.locatecontrol"
],
"allowedCommonJsDependencies": ["lodash", "leaflet.locatecontrol"],
"assets": [
"src/favicon.ico",
"src/assets",
......@@ -98,14 +95,10 @@
"ngswConfigPath": "ngsw-config.json"
},
"fr": {
"localize": [
"fr"
]
"localize": ["fr"]
},
"en": {
"localize": [
"en"
]
"localize": ["en"]
}
},
"defaultConfiguration": ""
......@@ -141,14 +134,8 @@
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets",
"src/manifest.webmanifest"
],
"styles": [
"src/styles.scss"
],
"assets": ["src/favicon.ico", "src/assets", "src/manifest.webmanifest"],
"styles": ["src/styles.scss"],
"scripts": []
}
},
......
module.exports = {
preset: 'jest-preset-angular',
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
moduleNameMapper: {
'@gouvfr-anct/(.*)': '<rootDir>/dist/@gouvfr-anct/$1',
},
};
import 'jest-preset-angular/jest-preset';
This diff is collapsed.
......@@ -4,7 +4,6 @@ import { PanelComponent } from './components/panel/panel.component';
import { ClaimStructureComponent } from './components/claim-structure/claim-structure.component';
import { ManageUsersComponent } from './components/manage-users/manage-users.component';
import { SharedModule } from '../shared/shared.module';
import { NewsletterUsersComponent } from './components/newsletter-users/newsletter-users.component';
import { AdminStructuresListComponent } from './components/structures-list/admin-structures-list.component';
import { ManageLockdownInfoComponent } from './components/lockdown-info/manage-lockdown-info.component';
import { AdminRoutingModule } from './admin-routing.module';
......@@ -26,7 +25,6 @@ import { JobPersonalOffer } from './components/manage-jobs/jobPersonalOffer/job-
declarations: [
PanelComponent,
ClaimStructureComponent,
NewsletterUsersComponent,
AdminStructuresListComponent,
ManageLockdownInfoComponent,
ManageUsersComponent,
......@@ -41,13 +39,13 @@ import { JobPersonalOffer } from './components/manage-jobs/jobPersonalOffer/job-
AdministredStructuresComponent,
AttachedUsersComponent,
ManageJobsComponent,
ManageEmployersComponent,
ManageEmployersComponent
],
imports: [
CommonModule,
AdminRoutingModule,
SharedModule,
AgGridModule.withComponents([DeleteUserComponent, AdministredStructuresComponent]),
],
AgGridModule.withComponents([DeleteUserComponent, AdministredStructuresComponent])
]
})
export class AdminModule {}
<div fxLayout="column" fxLayoutGap="5px" fxLayoutAlign="center center" class="userBlock">
<h2>Gestion abonnement newsletter</h2>
<div fxLayout="row" fxLayoutGap="20px" fxLayoutAlign="center center">
<button (click)="copySubscription()">Copier les adresses dans le presse papier</button>
<button (click)="searchSubscribedEmail('')">Afficher tous les inscrits</button>
</div>
<div fxLayout="row">Il y a actuellement {{ subscriptionsCount }} abonnés à la newsletter.</div>
<div fxLayout="row">
<input #searchstring (keyup)="(0)" />
<button (click)="searchSubscribedEmail(searchstring.value)">Rechercher</button>
</div>
<div class="userList">
<tr *ngFor="let subscription of subscriptions">
<td>{{ subscription.email }}</td>
<td>
<button (click)="toggleUnsubscribeModal(subscription.email)">Désabonner</button>
</td>
</tr>
<app-modal-confirmation
*ngIf="emailToUnsubscribe"
[openned]="deleteModalOpenned"
[content]="'Voulez-vous vraiment supprimer ' + emailToUnsubscribe + ' de la newsletter &nbsp;?'"
(closed)="unsubscribeEmail(emailToUnsubscribe, $event)"
></app-modal-confirmation>
<div *ngIf="subscriptions && subscriptions.length == 0">Aucun résultat</div>
</div>
</div>
import { Component } from '@angular/core';
import { NewsletterSubscription } from '../../../models/subscription-model';
import { AdminService } from '../../services/admin.service';
@Component({
selector: 'app-admin-newsletter-users',
templateUrl: './newsletter-users.component.html',
})
export class NewsletterUsersComponent {
public subscriptions: NewsletterSubscription[];
public deleteModalOpenned = false;
public emailToUnsubscribe: string = null;
public subscriptionsCount: number = 0;
constructor(private adminService: AdminService) {}
ngOnInit(): void {
this.adminService.countNewsletterSubscriptions().subscribe((count) => {
this.subscriptionsCount = count;
});
}
public toggleUnsubscribeModal(emailToUnsubscribe: string): void {
this.emailToUnsubscribe = emailToUnsubscribe;
this.deleteModalOpenned = !this.deleteModalOpenned;
}
public searchSubscribedEmail(searchString: string): void {
this.adminService.searchNewsletterSubscriptions(searchString).subscribe((emails) => {
this.subscriptions = emails;
});
}
public unsubscribeEmail(email: string, shouldUnsubscribe: boolean): void {
this.toggleUnsubscribeModal(email);
if (shouldUnsubscribe) {
this.adminService.unsubscribeEmail(email).subscribe((_data) => {
this.subscriptions = this.subscriptions.filter((obj) => obj.email !== email);
this.subscriptionsCount = this.subscriptions.length;
});
}
}
public copySubscription(): void {
this.adminService.searchNewsletterSubscriptions('').subscribe((emails) => {
let emailsToBeCopied = emails.map((e) => e.email).join(';');
let copyElement = document.createElement('textarea');
copyElement.textContent = decodeURI(emailsToBeCopied);
let body = document.getElementsByTagName('body')[0];
body.appendChild(copyElement);
copyElement.select();
document.execCommand('copy');
body.removeChild(copyElement);
});
}
}
......@@ -5,7 +5,6 @@
<button (click)="changeActiveFeature(features.structuresList)">Liste structures</button>
<button (click)="changeActiveFeature(features.manageUsers)">Gestion des utilisateurs</button>
<button (click)="changeActiveFeature(features.lockdownInfo)">Gestion des infos covid</button>
<button (click)="changeActiveFeature(features.newsletterUsers)">Newsletter</button>
<button (click)="changeActiveFeature(features.jobsList)">Fonctions</button>
<button (click)="changeActiveFeature(features.employersList)">Employeurs</button>
<a target="_blank" class="custom-link" rel="noopener noreferrer" [href]="ghostLink">Ghost</a>
......@@ -22,9 +21,6 @@
<div *ngIf="selectedFeature === features.lockdownInfo">
<app-admin-manage-lockdown-info></app-admin-manage-lockdown-info>
</div>
<div *ngIf="selectedFeature === features.newsletterUsers">
<app-admin-newsletter-users></app-admin-newsletter-users>
</div>
<div *ngIf="selectedFeature === features.jobsList">
<app-admin-manage-jobs></app-admin-manage-jobs>
</div>
......
......@@ -6,7 +6,7 @@ import { PanelRouteService } from '../../services/panel-route.service';
@Component({
selector: 'app-admin-panel',
templateUrl: './panel.component.html',
providers: [PanelRouteService],
providers: [PanelRouteService]
})
export class PanelComponent implements OnInit {
public features = AdminPannelEnum;
......
......@@ -8,6 +8,7 @@ import { OrientationFormComponent } from './form/orientation-form/orientation-fo
import { AdminGuard } from './guards/admin.guard';
import { AuthGuard } from './guards/auth.guard';
import { LoginGuard } from './guards/login.guard';
import { DeactivateGuard } from './guards/deactivate.guard';
import { LegalNoticeComponent } from './legal-notice/legal-notice.component';
import { LoginComponent } from './login/login.component';
import { NewsletterSubscriptionComponent } from './newsletter-subscription/newsletter-subscription.component';
......@@ -17,9 +18,10 @@ import { ResetEmailComponent } from './reset-email/reset-email.component';
import { ResetPasswordComponent } from './reset-password/reset-password.component';
import { StructureResolver } from './resolvers/structure.resolver';
import { PasswordFormComponent } from './shared/components';
import { StructureDetailsWrapperComponent } from './structure/components/structure-details-wrapper/structure-details-wrapper.component';
import { StructureExcludeComponent } from './structure/structure-exclude/structure-exclude.component';
import { StructureJoinComponent } from './structure/structure-join/structure-join.component';
import { StructureDetailsComponent } from './structure-list/components/structure-details/structure-details.component';
import { StructureListComponent } from './structure-list/structure-list.component';
import { StructureExcludeComponent } from './structure/structure-exclude/structure-exclude.component';
const footerOutletRoute: Route = {
path: '',
......@@ -31,7 +33,7 @@ const routes: Routes = [
{
path: 'print',
outlet: 'print',
children: [{ path: 'structure', component: StructureDetailsWrapperComponent }, footerOutletRoute],
children: [{ path: 'structure', component: StructureDetailsComponent }, footerOutletRoute],
},
{
path: 'print',
......@@ -58,7 +60,7 @@ const routes: Routes = [
{
path: '',
outlet: 'left-pane',
component: StructureDetailsWrapperComponent,
component: StructureDetailsComponent,
},
],
},
......@@ -72,6 +74,16 @@ const routes: Routes = [
footerOutletRoute,
],
},
{
path: 'structures',
children: [
{
path: '',
component: StructureListComponent,
},
footerOutletRoute,
],
},
{
path: 'legal-notice',
children: [
......@@ -140,7 +152,7 @@ const routes: Routes = [
path: '',
outlet: 'left-pane',
data: { fullScreen: true },
component: StructureDetailsWrapperComponent,
component: StructureDetailsComponent,
},
],
},
......
......@@ -4,6 +4,7 @@ import { ProfileService } from './profile/services/profile.service';
import { AuthService } from './services/auth.service';
import { RouterListenerService } from './services/routerListener.service';
import { UpdateService } from './services/update.service';
import { PrintService } from './shared/service/print.service';
@Component({
selector: 'app-root',
......@@ -15,6 +16,7 @@ export class AppComponent implements OnInit {
public loading = true;
constructor(
public printService: PrintService,
private authService: AuthService,
private profilService: ProfileService,
private routerListener: RouterListenerService,
......
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { LOCALE_ID, NgModule } from '@angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ServiceWorkerModule } from '@angular/service-worker';
import { GeometryPolygonConfiguration, MapModule, StructureModule } from '@gouvfr-anct/mediation-numerique';
import { ToastrModule } from 'ngx-toastr';
import metropole from '../assets/geojson/metropole.json';
import { environment } from '../environments/environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CartoComponent } from './carto/carto.component';
import { CustomBreakPointsProvider } from './config/custom-breakpoint';
import { CustomHttpInterceptor } from './config/http-interceptor';
import { InitialPosition } from './config/map/initial-position';
import { MarkerType } from './config/map/marker-type';
import { ZoomLevel } from './config/map/zoomLevel.enum';
import { ContactComponent } from './contact/contact.component';
import { FooterComponent } from './footer/footer.component';
import { FormViewModule } from './form/form-view/form-view.module';
import { OrientationComponent } from './form/orientation-form/component/orientation-modal/orientation-modal.component';
import { StructureDetailPrintComponent } from './form/orientation-form/component/structure-detail-print/structure-detail-print.component';
import { StructureListPrintComponent } from './form/orientation-form/component/structure-list-print/structure-list-print.component';
import { StructurePrintHeaderComponent } from './form/orientation-form/component/structure-print-header/structure-print-header.component';
import { OrientationFormComponent } from './form/orientation-form/orientation-form.component';
import { AdminGuard } from './guards/admin.guard';
import { AuthGuard } from './guards/auth.guard';
import { DeactivateGuard } from './guards/deactivate.guard';
import { LoginGuard } from './guards/login.guard';
import { RoleGuard } from './guards/role.guard';
import { HeaderComponent } from './header/header.component';
import { SharedModule } from './shared/shared.module';
import { MapModule } from './map/map.module';
import { StructureListComponent } from './structure-list/structure-list.component';
import { CardComponent } from './structure-list/components/card/card.component';
import { StructureListSearchComponent } from './structure-list/components/structure-list-search/structure-list-search.component';
import { StructureDetailsComponent } from './structure-list/components/structure-details/structure-details.component';
import { ModalFilterComponent } from './structure-list/components/modal-filter/modal-filter.component';
import { LegalNoticeComponent } from './legal-notice/legal-notice.component';
import { LoginComponent } from './login/login.component';
import { NewsletterSubscriptionComponent } from './newsletter-subscription/newsletter-subscription.component';
import { PageComponent } from './page/page.component';
import { ContactComponent } from './contact/contact.component';
import { AuthGuard } from './guards/auth.guard';
import { LoginGuard } from './guards/login.guard';
import { CustomHttpInterceptor } from './config/http-interceptor';
import { ResetEmailComponent } from './reset-email/reset-email.component';
import { ResetPasswordComponent } from './reset-password/reset-password.component';
import { StructureResolver } from './resolvers/structure.resolver';
import { AdminGuard } from './guards/admin.guard';
import { DeactivateGuard } from './guards/deactivate.guard';
import { TempUserResolver } from './resolvers/temp-user.resolver';
import { GeojsonService } from './services/geojson.service';
import { StructureJoinComponent } from './structure/structure-join/structure-join.component';
import { RouterListenerService } from './services/routerListener.service';
import { StructureService } from './services/structure.service';
import { NewsletterSubscriptionComponent } from './newsletter-subscription/newsletter-subscription.component';
import { OrientationFormComponent } from './form/orientation-form/orientation-form.component';
import { StructureDetailPrintComponent } from './form/orientation-form/component/structure-detail-print/structure-detail-print.component';
import { StructureListPrintComponent } from './form/orientation-form/component/structure-list-print/structure-list-print.component';
import { StructurePrintHeaderComponent } from './form/orientation-form/component/structure-print-header/structure-print-header.component';
import { OrientationComponent } from './form/orientation-form/component/orientation-modal/orientation-modal.component';
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';
import { StructureResolver } from './resolvers/structure.resolver';
import { RoleGuard } from './guards/role.guard';
import { UpdateService } from './services/update.service';
import { DataShareConsentComponent } from './shared/components/data-share-consent/data-share-consent.component';
import { SharedModule } from './shared/shared.module';
import { SearchService } from './structure-list/services/search.service';
import { StructureDetailsActionsComponent } from './structure/components/structure-details-actions/structure-details-actions.component';
import { StructureDetailsModalsComponent } from './structure/components/structure-details-modals/structure-details-modals.component';
import { StructureDetailsWrapperComponent } from './structure/components/structure-details-wrapper/structure-details-wrapper.component';
import { TclAccessComponent } from './structure/components/tcl-access/tcl-access.component';
import { FormViewModule } from './form/form-view/form-view.module';
import { LoginComponent } from './login/login.component';
import { StructureExcludeComponent } from './structure/structure-exclude/structure-exclude.component';
import { StructureJoinComponent } from './structure/structure-join/structure-join.component';
@NgModule({
declarations: [
......@@ -57,6 +53,11 @@ import { StructureJoinComponent } from './structure/structure-join/structure-joi
HeaderComponent,
FooterComponent,
CartoComponent,
StructureListComponent,
CardComponent,
StructureListSearchComponent,
ModalFilterComponent,
StructureDetailsComponent,
LegalNoticeComponent,
PageComponent,
ContactComponent,
......@@ -71,27 +72,16 @@ import { StructureJoinComponent } from './structure/structure-join/structure-joi
DataShareConsentComponent,
OrientationComponent,
LoginComponent,
TclAccessComponent,
StructureDetailsModalsComponent,
StructureDetailsActionsComponent,
StructureExcludeComponent,
StructureDetailsWrapperComponent,
],
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule,
SharedModule,
MapModule.forRoot(
metropole as GeometryPolygonConfiguration,
ZoomLevel,
InitialPosition,
MarkerType,
GeojsonService
),
MapModule,
BrowserAnimationsModule,
ToastrModule.forRoot(),
StructureModule.forRoot(SearchService, StructureService),
FormViewModule,
ServiceWorkerModule.register('ngsw-worker.js', {
enabled: environment.production,
......
......@@ -4,7 +4,6 @@
</div>
<div class="panes-container" fxLayout="row">
<app-structure-list
#ref
(searchEvent)="getStructures($event)"
[structureList]="structures"
[location]="currentLocation"
......@@ -13,29 +12,9 @@
[selectedStructure]="currentStructure"
(updatedStructure)="updateStructures($event)"
class="left-pane"
[ngClass]="{ mapPhone: isMapPhone === true }"
[ngClass]="{ mapPhone: isMapPhone == true }"
fxLayout="column"
>
<div slot="structure-list-actions">
<app-button
tabindex="0"
(action)="addStructure()"
[text]="'Ajouter une structure'"
[style]="buttonTypeEnum.Secondary"
[extraClass]="'small-text'"
></app-button>
</div>
<div slot="structure-list-elements">
<app-card
*ngFor="let structure of ref.structureList"
[structure]="structure"
[isClaimed]="isAdmin ? structure.isClaimed : true"
(showDetails)="ref.showDetails($event)"
(hover)="ref.handleCardHover($event)"
class="structure-card"
></app-card>
</div>
</app-structure-list>
></app-structure-list>
<div class="btnSwitch">
<app-button
[style]="buttonTypeEnum.ButtonPhone"
......@@ -52,7 +31,7 @@
[isMapPhone]="isMapPhone"
[searchedValue]="searchedValue"
class="right-pane"
[ngClass]="{ mapPhone: isMapPhone === true }"
[ngClass]="{ mapPhone: isMapPhone == true }"
></app-map>
</div>
</div>
import { Component, OnInit } from '@angular/core';
import { Meta } from '@angular/platform-browser';
import { ActivatedRoute, Router } from '@angular/router';
import { Filter, GeoJson, Structure } from '@gouvfr-anct/mediation-numerique';
import { ButtonType } from '@gouvfr-anct/mediation-numerique/shared';
import { ActivatedRoute } from '@angular/router';
import * as _ from 'lodash';
import { Observable } from 'rxjs';
import { GeoJson } from '../map/models/geojson.model';
import { ProfileService } from '../profile/services/profile.service';
import { AuthService } from '../services/auth.service';
import { Structure } from '../models/structure.model';
import { GeojsonService } from '../services/geojson.service';
import { StructureService } from '../services/structure.service';
import { ButtonType } from '../shared/components/button/buttonType.enum';
import { Filter } from '../structure-list/models/filter.model';
import { CustomRegExp } from '../utils/CustomRegExp';
import { Observable } from 'rxjs';
@Component({
selector: 'app-carto',
templateUrl: './carto.component.html',
styleUrls: ['./carto.component.scss'],
styleUrls: ['./carto.component.scss']
})
export class CartoComponent implements OnInit {
public filters: Filter[] = [];
......@@ -35,9 +36,7 @@ export class CartoComponent implements OnInit {
private geoJsonService: GeojsonService,
private activatedRoute: ActivatedRoute,
private profileService: ProfileService,
private meta: Meta,
private router: Router,
private authService: AuthService
private meta: Meta
) {}
ngOnInit(): void {
......@@ -55,7 +54,7 @@ export class CartoComponent implements OnInit {
this.meta.updateTag({
name: 'description',
content: 'Recense tous les lieux, accompagnements et ateliers de médiation numérique de la Métropole de Lyon.',
content: 'Recense tous les lieux, accompagnements et ateliers de médiation numérique de la Métropole de Lyon.'
});
}
......@@ -106,12 +105,7 @@ export class CartoComponent implements OnInit {
* @param lat user latitde
* @param sortByDistance if set to `true`, structures data is sort by distance. Default value is `true`
*/
private updateStructuresdistance(
structures: Structure[],
lon: number,
lat: number,
sortByDistance: boolean = true
): void {
private updateStructuresdistance(structures: Structure[], lon: number, lat: number, sortByDistance: boolean = true): void {
Promise.all(
structures.map(async (structure) => {
if (this.geolocation) {
......@@ -122,7 +116,7 @@ export class CartoComponent implements OnInit {
}
return structure;
})
).then(async (structureList: Structure[]) => {
).then((structureList) => {
if (sortByDistance) {
structureList = _.sortBy(structureList, ['distance']);
}
......@@ -160,10 +154,7 @@ export class CartoComponent implements OnInit {
* @param lat number
*/
private getStructurePosition(structure: Structure, lon: number, lat: number): Structure {
structure.distance = parseInt(
this.geoJsonService.getDistance(structure.getLat(), structure.getLon(), lat, lon, 'M'),
10
);
structure.distance = parseInt(this.geoJsonService.getDistance(structure.getLat(), structure.getLon(), lat, lon, 'M'), 10);
return structure;
}
......@@ -216,14 +207,6 @@ export class CartoComponent implements OnInit {
this.isMapPhone = !this.isMapPhone;
}
public addStructure(): void {
if (!this.authService.isLoggedIn()) {
this.router.navigateByUrl('/login');
} else {
this.router.navigateByUrl('/form/structure');
}
}
public get isAdmin(): boolean {
return this.profileService.isAdmin();
}
......