Definiowanie stałych globalnych

In Angular 1.x można zdefiniować stałe w następujący sposób:

angular.module('mainApp.config', [])
    .constant('API_ENDPOINT', 'http://127.0.0.1:6666/api/')

Jaki byłby odpowiednik w Angular (z maszynopisem)?

Po prostu nie chcę powtarzać podstawowego adresu URL API w kółko we wszystkich moich usługach.

Author: C_Ogoo, 2016-01-25

16 answers

Poniższe zmiany działają dla mnie na Angular 2 finalna wersja:

export class AppSettings {
   public static API_ENDPOINT='http://127.0.0.1:6666/api/';
}

A potem w serwisie:

import {Http} from 'angular2/http';
import {Message} from '../models/message';
import {Injectable} from 'angular2/core';
import {Observable} from 'rxjs/Observable';
import {AppSettings} from '../appSettings';
import 'rxjs/add/operator/map';

@Injectable()
export class MessageService {

    constructor(private http: Http) { }

    getMessages(): Observable<Message[]> {
        return this.http.get(AppSettings.API_ENDPOINT+'/messages')
            .map(response => response.json())
            .map((messages: Object[]) => {
                return messages.map(message => this.parseData(message));
            });
    }

    private parseData(data): Message {
        return new Message(data);
    }
}
 277
Author: AndreFeijo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-10 17:24:11

Rozwiązanie dla konfiguracji dostarczonej przez zespół angular można znaleźć tutaj .

Oto cały odpowiedni kod:

1) app.config.ts

import { OpaqueToken } from "@angular/core";

export let APP_CONFIG = new OpaqueToken("app.config");

export interface IAppConfig {
    apiEndpoint: string;
}

export const AppConfig: IAppConfig = {    
    apiEndpoint: "http://localhost:15422/api/"    
};

2) app.moduł.ts

import { APP_CONFIG, AppConfig } from './app.config';

@NgModule({
    providers: [
        { provide: APP_CONFIG, useValue: AppConfig }
    ]
})

3) twój.obsługa.ts

import { APP_CONFIG, IAppConfig } from './app.config';

@Injectable()
export class YourService {

    constructor(@Inject(APP_CONFIG) private config: IAppConfig) {
             // You can use config.apiEndpoint now
    }   
}

Teraz możesz wprowadzić konfigurację wszędzie bez używania nazw łańcuchów i przy użyciu interfejsu do kontroli statycznych.

Można oczywiście oddzielić interfejs i stałą dalej, aby móc dostarczyć różne wartości w produkcji i rozwoju np.

 167
Author: Ilya Chernomordik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-03 16:27:18

W Angular2, masz następującą definicję provide , która pozwala ustawić różne rodzaje zależności:

provide(token: any, {useClass, useValue, useExisting, useFactory, deps, multi}

W porównaniu do kątowej 1

app.service w Angular1 jest równoważne useClass W Angular2.

app.factory w Angular1 jest równoważne useFactory W Angular2.

app.constant i app.value został uproszczony do {[11] } z mniejszymi ograniczeniami. tzn. nie ma już config bloku.

app.provider - nie ma odpowiednika w Kątowa 2.

Przykłady

Do konfiguracji z wtryskiwaczem root:

bootstrap(AppComponent,[provide(API_ENDPOINT, { useValue='http://127.0.0.1:6666/api/' })]);

Lub konfiguracja z wtryskiwaczem twojego komponentu:

providers: [provide(API_ENDPOINT, { useValue: 'http://127.0.0.1:6666/api/'})]

provide jest krótką ręką dla:

var injectorValue = Injector.resolveAndCreate([
  new Provider(API_ENDPOINT, { useValue: 'http://127.0.0.1:6666/api/'})
]);

Z wtryskiwaczem uzyskanie wartości jest łatwe:

var endpoint = injectorValue.get(API_ENDPOINT);
 67
Author: pixelbits,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-12 17:05:04

Aktualizacja dla Angular 4 +

Teraz możemy po prostu użyć pliku environments, który angular zapewnia domyślne, jeśli twój projekt jest generowany przez angular-cli.

Na przykład

W folderze environments Utwórz następujące pliki

  • environment.prod.ts
  • environment.qa.ts
  • environment.dev.ts

I każdy plik może zawierać powiązane zmiany kodu takie as:

  • environment.prod.ts

    export const environment = {
         production: true,
         apiHost: 'https://api.somedomain.com/prod/v1/',
         CONSUMER_KEY: 'someReallyStupidTextWhichWeHumansCantRead', 
         codes: [ 'AB', 'AC', 'XYZ' ],
    };
    
  • environment.qa.ts

    export const environment = {
         production: false,
         apiHost: 'https://api.somedomain.com/qa/v1/',
         CONSUMER_KEY : 'someReallyStupidTextWhichWeHumansCantRead', 
         codes: [ 'AB', 'AC', 'XYZ' ],
    };
    
  • environment.dev.ts

    export const environment = {
         production: false,
         apiHost: 'https://api.somedomain.com/dev/v1/',
         CONSUMER_KEY : 'someReallyStupidTextWhichWeHumansCantRead', 
         codes: [ 'AB', 'AC', 'XYZ' ],
    };
    

Przypadek użycia w aplikacji

Możesz zaimportować środowiska do dowolnego pliku, takiego jak usługi clientUtilServices.ts

import {environment} from '../../environments/environment';

getHostURL(): string {
    return environment.apiHost;
  }

Przypadek użycia w budowie

Otwórz plik angular CLI .angular-cli.json i w środku "apps": [{...}] Dodaj następujący kod

 "apps":[{
        "environments": {
            "dev": "environments/environment.ts",
            "prod": "environments/environment.prod.ts",
            "qa": "environments/environment.qa.ts",
           }
         }
       ]

Jeśli chcesz zbudować dla produkcji, Uruchom ng build --env=prod odczyta konfigurację z environment.prod.ts, w ten sam sposób można to zrobić dla qa lub dev

# # starsza odpowiedź

Robiłem coś takiego jak poniżej, w moim providerze:

import {Injectable} from '@angular/core';

@Injectable()
export class ConstantService {

API_ENDPOINT :String;
CONSUMER_KEY : String;

constructor() {
    this.API_ENDPOINT = 'https://api.somedomain.com/v1/';
    this.CONSUMER_KEY = 'someReallyStupidTextWhichWeHumansCantRead'
  }
}

Wtedy mam dostęp do wszystkich stałych danych w dowolnym miejscu

import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/add/operator/map';

import {ConstantService} from  './constant-service'; //This is my Constant Service


@Injectable()
export class ImagesService {
    constructor(public http: Http, public ConstantService: ConstantService) {
    console.log('Hello ImagesService Provider');

    }

callSomeService() {

    console.log("API_ENDPOINT: ",this.ConstantService.API_ENDPOINT);
    console.log("CONSUMER_KEY: ",this.ConstantService.CONSUMER_KEY);
    var url = this.ConstantService.API_ENDPOINT;
    return this.http.get(url)
  }
 }
 66
Author: Anjum....,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-09 07:35:25

W Angular 4, możesz użyć klasy środowiska, aby zachować wszystkie swoje globale.

Masz środowisko.ts i środowisko.prod.ts domyślnie.

Na przykład

export const environment = {
  production: false,
  apiUrl: 'http://localhost:8000/api/'
};

A następnie w serwisie:

import { environment } from '../../environments/environment';
...
environment.apiUrl;
 65
Author: Nacho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-28 14:17:48

Chociaż podejście z klasą AppSettings ze stałą łańcuchową jako apiendpoint działa, nie jest idealne, ponieważ nie moglibyśmy zamienić tego prawdziwego ApiEndpoint na inne wartości w czasie testów jednostkowych.

Musimy być w stanie wprowadzić te punkty końcowe api do naszych usług (pomyśl o wstrzyknięciu usługi do innej usługi). Nie musimy również tworzyć całej klasy do tego, wszystko co chcemy zrobić, to wstrzyknąć łańcuch do naszych usług będący naszym ApiEndpoint. Na uzupełnij doskonałą odpowiedź przez pixelbits, Oto Pełny kod, jak można to zrobić w Angular 2:

Najpierw musimy powiedzieć Angular, jak dostarczyć instancję naszego punktu ApiEndpoint, gdy poprosimy o nią w naszej aplikacji (pomyśl o tym, jak o zarejestrowaniu zależności):

bootstrap(AppComponent, [
        HTTP_PROVIDERS,
        provide('ApiEndpoint', {useValue: 'http://127.0.0.1:6666/api/'})
]);         


A następnie w serwisie wstrzykujemy ten punkt ApiEndpoint do konstruktora serwisu i Angular dostarczy nam go na podstawie naszej rejestracji powyżej:

import {Http} from 'angular2/http';
import {Message} from '../models/message';
import {Injectable, Inject} from 'angular2/core';  // * We import Inject here
import {Observable} from 'rxjs/Observable';
import {AppSettings} from '../appSettings';
import 'rxjs/add/operator/map';

@Injectable()
export class MessageService {

    constructor(private http: Http, 
                @Inject('ApiEndpoint') private apiEndpoint: string) { }

    getMessages(): Observable<Message[]> {
        return this.http.get(`${this.apiEndpoint}/messages`)
            .map(response => response.json())
            .map((messages: Object[]) => {
                return messages.map(message => this.parseData(message));
            });
    } 
    // the rest of the code...
}
 34
Author: Morteza Manavi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:54

Oto moje ostatnie doświadczenia z tym scenariuszem:

  • @kątowe / cli: 1.0.0
  • węzeł: 6.10.2
  • @kątowe / rdzeniowe: 4.0.0

Śledziłem oficjalne i zaktualizowane dokumenty tutaj:

Https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#dependency-injection-tokens

Wydaje się OpaqueToken jest teraz przestarzały i musimy użyć InjectionToken , więc są to moje pliki uruchamiane jak czar:

app-config.interface.ts

export interface IAppConfig {

  STORE_KEY: string;

}

app-config.constants.ts

import { InjectionToken } from "@angular/core";
import { IAppConfig } from "./app-config.interface";

export const APP_DI_CONFIG: IAppConfig = {

  STORE_KEY: 'l@_list@'

};

export let APP_CONFIG = new InjectionToken< IAppConfig >( 'app.config' );

app.module.ts

import { APP_CONFIG, APP_DI_CONFIG } from "./app-config/app-config.constants";

@NgModule( {
  declarations: [ ... ],
  imports: [ ... ],
  providers: [
    ...,
    {
      provide: APP_CONFIG,
      useValue: APP_DI_CONFIG
    }
  ],
  bootstrap: [ ... ]
} )
export class AppModule {}

my-service.service.ts

  constructor( ...,
               @Inject( APP_CONFIG ) private config: IAppConfig) {

    console.log("This is the App's Key: ", this.config.STORE_KEY);
    //> This is the App's Key:  l@_list@

  }

Wynik jest czysty i nie ma żadnych ostrzeżeń na konsoli dziękuję za ostatni komentarz Johna papy w tym numerze:

Https://github.com/angular/angular-cli/issues/2034

Klucz został zaimplementowany w innym pliku interfejsu.

 31
Author: JavierFuentes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-27 22:44:18

Wszystkie rozwiązania wydają się być skomplikowane. Szukam najprostszego rozwiązania dla tej sprawy i chcę tylko użyć stałych. Stałe są proste. Czy jest coś, co przemawia przeciwko poniższemu rozwiązaniu?

App.const.ts

'use strict';

export const dist = '../path/to/dist/';

App.obsługa.ts

import * as AppConst from '../app.const'; 

@Injectable()
export class AppService {

    constructor (
    ) {
        console.log('dist path', AppConst.dist );
    }

}
 22
Author: Alexander K. J. Schmidt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-03 16:37:19

Wystarczy użyć stałej maszynopisu

export var API_ENDPOINT = 'http://127.0.0.1:6666/api/';

Możesz go użyć w iniektorze zależności używając

bootstrap(AppComponent, [provide(API_ENDPOINT, {useValue: 'http://127.0.0.1:6666/api/'}), ...]);
 12
Author: SnareChops,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-25 07:12:01

Jeśli używasz Webpack, co polecam, możesz ustawić stałe dla różnych środowisk. Jest to szczególnie cenne, gdy masz różne stałe wartości w zależności od środowiska.

Prawdopodobnie będziesz mieć wiele plików webpack w katalogu /config (np.dev.js, webpack.prod.js itp.). Wtedy będziesz miał custom-typings.d.ts dodasz je tam. Oto ogólny wzór do naśladowania w każdym pliku i przykładowe użycie w Komponent.

Webpack.{env}.js

const API_URL = process.env.API_URL = 'http://localhost:3000/';
const JWT_TOKEN_NAME = "id_token";
...
    plugins: [
      // NOTE: when adding more properties, make sure you include them in custom-typings.d.ts
      new DefinePlugin({
        'API_URL': JSON.stringify(API_URL),
        'JWT_TOKEN_NAME': JSON.stringify(JWT_TOKEN_NAME)
      }),

Niestandardowe typy.d. ts

declare var API_URL: string;
declare var JWT_TOKEN_NAME: string;
interface GlobalEnvironment {
  API_URL: string;
  JWT_TOKEN_NAME: string;
}

Komponent

export class HomeComponent implements OnInit {
  api_url:string = API_URL;
  authToken: string = "Bearer " + localStorage.getItem(JWT_TOKEN_NAME)});
}
 5
Author: occasl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-20 21:33:43

Jednym z podejść do Angular4 byłoby zdefiniowanie stałej na poziomie modułu:

const api_endpoint = 'http://127.0.0.1:6666/api/';

@NgModule({
  declarations: [AppComponent],
  bootstrap: [AppComponent],
  providers: [
    MessageService,
    {provide: 'API_ENDPOINT', useValue: api_endpoint}
  ]
})
export class AppModule {
}

Następnie, w służbie:

import {Injectable, Inject} from '@angular/core';

@Injectable()
export class MessageService {

    constructor(private http: Http, 
      @Inject('API_ENDPOINT') private api_endpoint: string) { }

    getMessages(): Observable<Message[]> {
        return this.http.get(this.api_endpoint+'/messages')
            .map(response => response.json())
            .map((messages: Object[]) => {
                return messages.map(message => this.parseData(message));
            });
    }

    private parseData(data): Message {
        return new Message(data);
    }
}
 5
Author: Juangui Jordán,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-26 12:43:48

Mam inny sposób definiowania stałych globalnych. Ponieważ jeśli zdefiniowaliśmy w pliku ts, jeśli zbudowaliśmy w trybie produkcyjnym, nie jest łatwo znaleźć stałe do zmiany wartości.

export class SettingService  {

  constructor(private http: HttpClient) {

  }

  public getJSON(file): Observable<any> {
      return this.http.get("./assets/configs/" + file + ".json");
  }
  public getSetting(){
      // use setting here
  }
}

W folderze aplikacji dodaję folder configs / setting.json

Zawartość w ustawieniu.json

{
    "baseUrl": "http://localhost:52555"
}

W module aplikacji Dodaj APP_INITIALIZER

   {
      provide: APP_INITIALIZER,
      useFactory: (setting: SettingService) => function() {return setting.getSetting()},
      deps: [SettingService],
      multi: true
    }

W ten sposób mogę łatwiej zmienić wartość w pliku json. Używam również tego sposobu do ciągłych komunikatów o błędach / ostrzeżeniach.

 4
Author: Hien Nguyen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-15 09:19:37

Używanie pliku właściwości generowanego podczas budowania jest proste i łatwe. Jest to podejście, które kątowe CLI używa. Zdefiniuj Plik Właściwości dla każdego środowiska i użyj polecenia podczas kompilacji, aby określić, który plik zostanie skopiowany do aplikacji. Następnie po prostu zaimportuj plik właściwości do użycia.

Https://github.com/angular/angular-cli#build-targets-and-environment-files

 3
Author: R.Creager,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-10 04:00:54

AngularJS module.constant nie definiuje stałej w sensie standardowym.

Chociaż jest on sam jako mechanizm rejestracji dostawcy, najlepiej jest rozumieć go w kontekście powiązanych module.value ($provide.value) funkcja. Oficjalna dokumentacja jasno określa przypadek użycia:

Zarejestruj usługę wartości za pomocą $injector, taką jak łańcuch znaków, liczba, tablica, obiekt lub funkcja. Jest to skrót od rejestracji usługi, w której jego właściwość $get jest funkcja factory, która nie pobiera argumentów i zwraca usługę value. Oznacza to również, że nie jest możliwe wstrzyknięcie innych usług do usługi wartości.

Porównaj to z dokumentacją dla module.constant ($provide.constant) co również jasno określa przypadek użycia (podkreślenie mine):

Zarejestruj stałą usługę za pomocą $injector, taką jak łańcuch znaków, liczba, tablica, obiekt lub funkcja. Podobnie jak wartość, nie jest możliwe wstrzyknięcie innych usług do stałej. Ale w przeciwieństwie do wartości, stała może być wprowadzana do funkcji konfiguracyjnej modułu(patrz kąt.Moduł) i nie może być nadpisany przez dekorator AngularJS .

Dlatego funkcja AngularJS constant nie zapewnia stałej w powszechnie rozumianym znaczeniu tego terminu w polu.

To powiedziawszy ograniczenia nałożone na dostarczony obiekt, wraz z jego wcześniejszą dostępnością za pośrednictwem $injector, wyraźnie sugeruje, że nazwa jest używana przez analogia.

Jeśli chcesz mieć stałą w aplikacji AngularJS, "podaj" ją tak samo jak w każdym programie JavaScript, który jest

export const π = 3.14159265;

W kątowym 2 stosuje się tę samą technikę.

Aplikacje Angular 2 nie mają fazy konfiguracji w tym samym sensie, co Aplikacje AngularJS. Ponadto nie ma mechanizmu dekoratora usługi (AngularJS dekorator ), ale nie jest to szczególnie zaskakujące, biorąc pod uwagę, jak różne są od siebie.

Przykład

angular
  .module('mainApp.config', [])
  .constant('API_ENDPOINT', 'http://127.0.0.1:6666/api/');

Jest niejasno arbitralne i nieco odpychające, ponieważ $provide.constant jest używany do określenia obiektu, który jest nawiasem mówiąc również stałą. Równie dobrze mogłeś napisać

export const apiEndpoint = 'http://127.0.0.1:6666/api/';

Dla wszystkich, które mogą się zmienić.

Teraz argument za testowalnością, wyśmiewając stałą, jest pomniejszony, ponieważ dosłownie się nie zmienia.

Nie wyśmiewa się π.

Oczywiście twoje podanie specyficzną semantyką może być zmiana punktu końcowego API lub nieprzezroczysty mechanizm przełączania awaryjnego, więc w pewnych okolicznościach rozsądne byłoby, aby punkt końcowy API uległ zmianie.

Ale w takim przypadku podanie go jako ciąg znaków literalnej reprezentacji pojedynczego adresu URL do funkcji constant nie zadziałałoby.

Lepszym argumentem i prawdopodobnie jeszcze jednym z powodów istnienia funkcji AngularJS $provide.constant jest to, że gdy AngularJS został wprowadzony, JavaScript nie miał standardowej koncepcji modułu. W takim przypadku globale byłyby używane do dzielenia się wartościami, zmiennymi lub niezmiennymi, a używanie globali jest problematyczne.

To powiedziawszy, dostarczenie czegoś takiego poprzez ramy zwiększa powiązanie z tymi ramami. Łączy również logikę kątową z logiką, która działa w każdym innym systemie.

To nie znaczy, że jest to złe lub szkodliwe podejście, ale osobiście, jeśli chcę stała W Angular 2 application, I will write

export const π = 3.14159265;

Tak jak ja używałbym AngularJS.

Im więcej rzeczy się zmienia...
 0
Author: Aluan Haddad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-27 00:50:24

Najlepszym sposobem tworzenia stałych szerokich aplikacji w Angular 2 jest użycie środowiska.pliki ts. Zaletą deklarowania takich stałych jest to, że można je zmieniać w zależności od środowiska, ponieważ dla każdego środowiska może istnieć inny plik środowiskowy.

 0
Author: Hassan Arafat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-18 16:08:30

Możesz utworzyć klasę dla zmiennej globalnej, a następnie wyeksportować tę klasę w następujący sposób:

export class CONSTANT {
    public static message2 = [
        { "NAME_REQUIRED": "Name is required" }
    ]

    public static message = {
        "NAME_REQUIRED": "Name is required",
    }
}

Po utworzeniu i wyeksportowaniu klasy CONSTANT, powinieneś zaimportować tę klasę do tej klasy, której chcesz użyć, w następujący sposób:

import { Component, OnInit                       } from '@angular/core';
import { CONSTANT                                } from '../../constants/dash-constant';


@Component({
  selector   : 'team-component',
  templateUrl: `../app/modules/dashboard/dashComponents/teamComponents/team.component.html`,
})

export class TeamComponent implements OnInit {
  constructor() {
    console.log(CONSTANT.message2[0].NAME_REQUIRED);
    console.log(CONSTANT.message.NAME_REQUIRED);
  }

  ngOnInit() {
    console.log("oninit");
    console.log(CONSTANT.message2[0].NAME_REQUIRED);
    console.log(CONSTANT.message.NAME_REQUIRED);
  }
}

Możesz użyć tego w constructor lub ngOnInit(){}, lub w dowolnych predefiniowanych metodach.

 -1
Author: Shubham Verma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-22 10:11:10