/**
   * @internal
   */
resolveMiddleware(
    clientStack: MiddlewareStack<ServiceInputTypes, ServiceOutputTypes>,
    configuration: AppRunnerClientResolvedConfig,
    options?: __HttpHandlerOptions
  ): Handler<PauseServiceCommandInput, PauseServiceCommandOutput> {
    this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize));

    const stack = clientStack.concat(this.middlewareStack);

    const { logger } = configuration;
    const clientName = "AppRunnerClient";
    const commandName = "PauseServiceCommand";
    const handlerExecutionContext: HandlerExecutionContext = {
      logger,
      clientName,
      commandName,
      inputFilterSensitiveLog: PauseServiceRequest.filterSensitiveLog,
      outputFilterSensitiveLog: PauseServiceResponse.filterSensitiveLog,
    };
    const { requestHandler } = configuration;
    return stack.resolve(
      (request: FinalizeHandlerArguments<any>) =>
        requestHandler.handle(request.request as __HttpRequest, options || {}),
      handlerExecutionContext
    );
  }


private serialize(input: PauseServiceCommandInput, context: __SerdeContext): Promise<__HttpRequest> {
    return serializeAws_json1_0PauseServiceCommand(input, context);
  }


private deserialize(output: __HttpResponse, context: __SerdeContext): Promise<PauseServiceCommandOutput> {
    return deserializeAws_json1_0PauseServiceCommand(output, context);
  }


/**
 * Created with https://github.com/flowup/api-client-generator
 */
@Injectable()
export class MetaAPIClient implements MetaAPIClientInterface {

  readonly options: APIHttpOptions;

  readonly domain: string = `https://api.github.com`;

  constructor(private readonly http: HttpClient,
              @Optional() @Inject(USE_DOMAIN) domain?: string,
              @Optional() @Inject(USE_HTTP_OPTIONS) options?: DefaultHttpOptions) {

    if (domain != null) {
      this.domain = domain;
    }

    this.options = {
      headers: new HttpHeaders(options && options.headers ? options.headers : {}),
      params: new HttpParams(options && options.params ? options.params : {}),
      ...(options && options.reportProgress ? { reportProgress: options.reportProgress } : {}),
      ...(options && options.withCredentials ? { withCredentials: options.withCredentials } : {})
    };
  }

  /**
   * This gives some information about GitHub.com, the service.
   */
  getMeta(
    args: {
      xGitHubMediaType?: string,  // (optional) You can check the current version of media type in responses.
      accept?: string,  // (optional) Is used to set specified media type.
      xRateLimitLimit?: number,
      xRateLimitRemaining?: number,
      xRateLimitReset?: number,
      xGitHubRequestId?: number,
    },
    requestHttpOptions?: HttpOptions
  ): Observable<models.Meta> {
    const path = `/meta`;
    const options: APIHttpOptions = {...this.options, ...requestHttpOptions};

    if ('xGitHubMediaType' in args) {
      options.headers = options.headers.set('X-GitHub-Media-Type', String(args.xGitHubMediaType));
    }
    if ('accept' in args) {
      options.headers = options.headers.set('Accept', String(args.accept));
    }
    if ('xRateLimitLimit' in args) {
      options.headers = options.headers.set('X-RateLimit-Limit', String(args.xRateLimitLimit));
    }
    if ('xRateLimitRemaining' in args) {
      options.headers = options.headers.set('X-RateLimit-Remaining', String(args.xRateLimitRemaining));
    }
    if ('xRateLimitReset' in args) {
      options.headers = options.headers.set('X-RateLimit-Reset', String(args.xRateLimitReset));
    }
    if ('xGitHubRequestId' in args) {
      options.headers = options.headers.set('X-GitHub-Request-Id', String(args.xGitHubRequestId));
    }
    return this.sendRequest<models.Meta>('GET', path, options);
  }

  private sendRequest<T>(method: string, path: string, options: HttpOptions, body?: any): Observable<T> {
    switch (method) {
      case 'DELETE':
        return this.http.delete<T>(`${this.domain}${path}`, options);
      case 'GET':
        return this.http.get<T>(`${this.domain}${path}`, options);
      case 'HEAD':
        return this.http.head<T>(`${this.domain}${path}`, options);
      case 'OPTIONS':
        return this.http.options<T>(`${this.domain}${path}`, options);
      case 'PATCH':
        return this.http.patch<T>(`${this.domain}${path}`, body, options);
      case 'POST':
        return this.http.post<T>(`${this.domain}${path}`, body, options);
      case 'PUT':
        return this.http.put<T>(`${this.domain}${path}`, body, options);
      default:
        console.error(`Unsupported request: ${method}`);
        return throwError(`Unsupported request: ${method}`);
    }
  }
}


type APIHttpOptions = HttpOptions & {
  headers: HttpHeaders;
  params: HttpParams;
};


/**
   * This gives some information about GitHub.com, the service.
   */
getMeta(
    args: {
      xGitHubMediaType?: string,  // (optional) You can check the current version of media type in responses.
      accept?: string,  // (optional) Is used to set specified media type.
      xRateLimitLimit?: number,
      xRateLimitRemaining?: number,
      xRateLimitReset?: number,
      xGitHubRequestId?: number,
    },
    requestHttpOptions?: HttpOptions
  ): Observable<models.Meta> {
    const path = `/meta`;
    const options: APIHttpOptions = {...this.options, ...requestHttpOptions};

    if ('xGitHubMediaType' in args) {
      options.headers = options.headers.set('X-GitHub-Media-Type', String(args.xGitHubMediaType));
    }
    if ('accept' in args) {
      options.headers = options.headers.set('Accept', String(args.accept));
    }
    if ('xRateLimitLimit' in args) {
      options.headers = options.headers.set('X-RateLimit-Limit', String(args.xRateLimitLimit));
    }
    if ('xRateLimitRemaining' in args) {
      options.headers = options.headers.set('X-RateLimit-Remaining', String(args.xRateLimitRemaining));
    }
    if ('xRateLimitReset' in args) {
      options.headers = options.headers.set('X-RateLimit-Reset', String(args.xRateLimitReset));
    }
    if ('xGitHubRequestId' in args) {
      options.headers = options.headers.set('X-GitHub-Request-Id', String(args.xGitHubRequestId));
    }
    return this.sendRequest<models.Meta>('GET', path, options);
  }


private sendRequest<T>(method: string, path: string, options: HttpOptions, body?: any): Observable<T> {
    switch (method) {
      case 'DELETE':
        return this.http.delete<T>(`${this.domain}${path}`, options);
      case 'GET':
        return this.http.get<T>(`${this.domain}${path}`, options);
      case 'HEAD':
        return this.http.head<T>(`${this.domain}${path}`, options);
      case 'OPTIONS':
        return this.http.options<T>(`${this.domain}${path}`, options);
      case 'PATCH':
        return this.http.patch<T>(`${this.domain}${path}`, body, options);
      case 'POST':
        return this.http.post<T>(`${this.domain}${path}`, body, options);
      case 'PUT':
        return this.http.put<T>(`${this.domain}${path}`, body, options);
      default:
        console.error(`Unsupported request: ${method}`);
        return throwError(`Unsupported request: ${method}`);
    }
  }


() => ({
    authInfo: null as IAuthInfo | null
  })


(role: string): boolean => {
        if (this.authInfo === null) return false
        role = role.toLowerCase()
        return !!this.authInfo.userRoles.find(r => r.toLowerCase() === role)
      }


r => r.toLowerCase() === role


(roles: string[]): boolean => {
        if (this.authInfo === null) return false
        return this.authInfo.userRoles.some(v => roles.find(r => r.toLowerCase() === v.toLowerCase()))
      }


v => roles.find(r => r.toLowerCase() === v.toLowerCase())


r => r.toLowerCase() === v.toLowerCase()


export interface IAuthInfo {
  accessToken: string
  accessTokenExpiration: Date | null
  userName: string
  userRoles: string[]
}


isAuthenticated(): boolean {
      if (this.authInfo !== null && this.authInfo.accessToken) {
        // check exp
        if (new Date() <= (this.authInfo.accessTokenExpiration as Date)) return true
      }

      return false
    }


userName(): string {
      return this.authInfo?.userName ?? ''
    }


isUserInRole() {
      return (role: string): boolean => {
        if (this.authInfo === null) return false
        role = role.toLowerCase()
        return !!this.authInfo.userRoles.find(r => r.toLowerCase() === role)
      }
    }


isUserInAnyRole() {
      return (roles: string[]): boolean => {
        if (this.authInfo === null) return false
        return this.authInfo.userRoles.some(v => roles.find(r => r.toLowerCase() === v.toLowerCase()))
      }
    }


updateToken(token: string): void {
      const decode = jwt_decode<any>(token)
      let role = decode['http://schemas.microsoft.com/ws/2008/06/identity/claims/role']
      if (!Array.isArray(role))
        role = [role]

      this.authInfo = {
        accessToken: token,
        userName: decode['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name'],
        userRoles: role,
        accessTokenExpiration: new Date(decode.exp * 1000)
      }
      axios.defaults.headers.common.Authorization = `Bearer ${token}`
    }


clearToken(): void {
      this.authInfo = null
    }


login(token: string): void {
      this.updateToken(token)
      localStorage.setItem('token', token)
    }


logout(): void {
      this.clearToken()
      delete axios.defaults.headers.common.Authorization
      localStorage.removeItem('token')
    }


@Injectable()
export class CurrentUserMiddleware implements NestMiddleware {
  constructor(private usersService: UsersService) {}
  async use(req: Request, res: Response, next: NextFunction) {
    const { userId } = req.session || {};

    if (userId) {
      const user = await this.usersService.findOne(userId);

      req.currentUser = user;
    }
    next();
  }
}


interface Request {
      currentUser?: User;
    }


async use(req: Request, res: Response, next: NextFunction) {
    const { userId } = req.session || {};

    if (userId) {
      const user = await this.usersService.findOne(userId);

      req.currentUser = user;
    }
    next();
  }


(
	Network,
	waitFor: number,
): Promise<void> => new Promise((resolve) => {
	const trackRequests = new Set();
	let resolvingTimeout = setTimeout(resolve, waitFor);

	Network.requestWillBeSent(({ requestId }) => {
		trackRequests.add(requestId);
		clearTimeout(resolvingTimeout);
	});

	Network.loadingFinished(({ requestId }) => {
		trackRequests.delete(requestId);
		if (trackRequests.size === 0) {
			resolvingTimeout = setTimeout(resolve, waitFor);
		}
	});
})


(resolve) => {
	const trackRequests = new Set();
	let resolvingTimeout = setTimeout(resolve, waitFor);

	Network.requestWillBeSent(({ requestId }) => {
		trackRequests.add(requestId);
		clearTimeout(resolvingTimeout);
	});

	Network.loadingFinished(({ requestId }) => {
		trackRequests.delete(requestId);
		if (trackRequests.size === 0) {
			resolvingTimeout = setTimeout(resolve, waitFor);
		}
	});
}


({ requestId }) => {
		trackRequests.add(requestId);
		clearTimeout(resolvingTimeout);
	}


({ requestId }) => {
		trackRequests.delete(requestId);
		if (trackRequests.size === 0) {
			resolvingTimeout = setTimeout(resolve, waitFor);
		}
	}


(ms: number): Promise<void> => new Promise((resolve) => {
	setTimeout(resolve, ms);
})


(resolve) => {
	setTimeout(resolve, ms);
}


async (
	DOM,
	contextNodeId: number,
	selector: string,
) => await pRetry(
	async () => {
		const { nodeId } = await DOM.querySelector({
			nodeId: contextNodeId,
			selector,
		});

		if (nodeId === 0) {
			throw new Error(`Selector "${selector}" not found`);
		}

		return nodeId as number;
	},
	{
		retries: 3,
		onFailedAttempt: async () => await sleep(100),
	},
)


async () => {
		const { nodeId } = await DOM.querySelector({
			nodeId: contextNodeId,
			selector,
		});

		if (nodeId === 0) {
			throw new Error(`Selector "${selector}" not found`);
		}

		return nodeId as number;
	}


async () => await sleep(100)


async (
	DOM,
	query: string,
) => {
	const { searchId, resultCount } = await DOM.performSearch({ query });
	const { nodeIds } = await DOM.getSearchResults({
		searchId,
		fromIndex: 0,
		toIndex: resultCount,
	});

	return nodeIds as number[];
}


async (
	DOM,
	nodeId: number,
) => {
	await DOM.setAttributeValue({
		nodeId,
		name: 'style',
		value: 'visibility: hidden',
	});
}


async (
	Page,
	DOM,
	nodeId: number,
) => {
	try {
		const { model } = await DOM.getBoxModel({ nodeId });
		const screenshot = await Page.captureScreenshot({
			clip: {
				x: 0,
				y: 0,
				width: model.width,
				height: model.height,
				scale: 1,
			},
		});

		return Buffer.from(screenshot.data, 'base64');
	} catch (error) {
		console.log(error);
		throw new Error('Failed to take a snapshot');
	}
}


(data:any)=> {
      setTimeout(()=> {
        this.smses = data;
      }, 0)

    }


()=> {
        this.smses = data;
      }


(error:any)=> {
      alert(error);
    }


/*
 Generated class for the Home page.

 See http://ionicframework.com/docs/v2/components/#navigation for more info on
 Ionic pages and navigation.
 */
@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
  public smses:any;

  constructor(public navCtrl:NavController, public platform:Platform) {

  }

  ionViewDidLoad() {
    console.log('ionViewDidLoad HomePage');
  }

  getSMS() {
    if (window.SMS) window.SMS.listSMS({}, (data:any)=> {
      setTimeout(()=> {
        this.smses = data;
      }, 0)

    }, (error:any)=> {
      alert(error);
    });
  }

}


ionViewDidLoad() {
    console.log('ionViewDidLoad HomePage');
  }


getSMS() {
    if (window.SMS) window.SMS.listSMS({}, (data:any)=> {
      setTimeout(()=> {
        this.smses = data;
      }, 0)

    }, (error:any)=> {
      alert(error);
    });
  }


export function isSuperbalanced(tree: BinaryTreeNode) {
  const nodes = [{ depth: 0, node: tree }];
  const leafDepths: number[] = [];

  while (nodes.length) {
    const { depth, node } = nodes.pop();

    if (!node.left && !node.right && !leafDepths.includes(depth)) {
      leafDepths.push(depth);
      if (Math.max(...leafDepths) - Math.min(...leafDepths) > 1) {
        return false;
      }
    }

    if (node.left) {
      nodes.push({ depth: depth + 1, node: node.left });
    }

    if (node.right) {
      nodes.push({ depth: depth + 1, node: node.right });
    }
  }

  return true;
}


async (store: IDocumentStore) => {
    const patch = new PatchByQueryOperation(`from Products as p
    update {
        p.setup = {
            fee: 0,
            description: ''
        }
    }`);
    const operation = await store.operations.send(patch);
    await operation.waitForCompletion();
  }


async () => {
    console.log('2020-11-26-PatchProductsWithSetup > down');
  }


export async function revertLiveShareWorkspaceColors() {
  await updateWorkspaceConfiguration(peacockColorCustomizations);

  peacockColorCustomizations = null;
}


async function setLiveShareSessionWorkspaceColors(isHost: boolean) {
  const colorSettingName = isHost
    ? LiveShareSettings.VSLSShareColor
    : LiveShareSettings.VSLSJoinColor;

  const liveShareColorSetting = getLiveShareColor(colorSettingName);
  if (!liveShareColorSetting) {
    return;
  }

  await applyColor(liveShareColorSetting);
}


export async function refreshLiveShareSessionColor(isHostRole: boolean): Promise<boolean> {
  const vslsApi = await vsls.getApi();

  // not in Live Share session, no need to update
  if (!vslsApi || !vslsApi.session.id) {
    const verb = isHostRole ? 'host and share' : 'join';

    notify(`The selected color will be applied every time you ${verb} a Live Share session.`, true);

    return false;
  }

  const isHost = vslsApi.session.role === vsls.Role.Host;
  await setLiveShareSessionWorkspaceColors(isHost);
  return true;
}


export async function addLiveShareIntegration(context: vscode.ExtensionContext) {
  State.extensionContext = context;

  registerLiveShareIntegrationCommands();

  const vslsApi = await vsls.getApi();
  await vscode.commands.executeCommand('setContext', 'peacock:liveshare', !!vslsApi);

  if (!vslsApi) {
    return;
  }

  vslsApi!.onDidChangeSession(async e => {
    // If there isn't a session ID, then that
    // means the session has been ended.
    if (!e.session.id) {
      return await revertLiveShareWorkspaceColors();
    }

    // we need to update `peacockColorCustomizations` only when it is `undefined`
    // to prevent the case of multiple color changes during live share session
    peacockColorCustomizations = await getColorCustomizationConfigFromWorkspace();

    const isHost = e.session.role === vsls.Role.Host;
    return await setLiveShareSessionWorkspaceColors(isHost);
  });
}


async e => {
    // If there isn't a session ID, then that
    // means the session has been ended.
    if (!e.session.id) {
      return await revertLiveShareWorkspaceColors();
    }

    // we need to update `peacockColorCustomizations` only when it is `undefined`
    // to prevent the case of multiple color changes during live share session
    peacockColorCustomizations = await getColorCustomizationConfigFromWorkspace();

    const isHost = e.session.role === vsls.Role.Host;
    return await setLiveShareSessionWorkspaceColors(isHost);
  }


(data: {}) => {
          this.persona = data[0];
          this.personaldataService.findDataUser('https://servicios.espe.edu.ec:8443/miEspeRPWS-0.0.1-SNAPSHOT/restWs/userldap/',this.userName).subscribe(
            data =>{
              this.personaldataService.findDataUser('https://miespemovil.espe.edu.ec/reportes/reporteWs/cedulaById/',data.).subscribe(
                data =>{

                }
              )
            }
          )
          console.log('USUARIO', this.persona.pidm);
          this.initialiseInvites(this.persona.pidm);
        }


data =>{
              this.personaldataService.findDataUser('https://miespemovil.espe.edu.ec/reportes/reporteWs/cedulaById/',data.).subscribe(
                data =>{

                }
              )
            }


data =>{

                }


@Component({
  selector: 'app-sidebar',
  templateUrl: './sidebar.component.html',
  styleUrls: ['./sidebar.component.css']
})
export class SidebarComponent implements OnInit {
  public isLoggedIn = false;
  public userName: string;
  menuSolicitudes: any[];
  menuPlanificaciones: any[];
  menuAsistencias: any[];
  menuListados: any[];

  persona: any = [];

  menuItems: any[];
  menuItems2: any[];
  menuItems3: any[];
  menuItems4: any[];

  usuarioData: any=[];
  pidm;
  id;
  usuario: any;
  spidem;

  constructor(private authService:AuthService, private personaldataService:PersonalDataService,private router: Router,private restService: RestService) { }

  ngOnInit() {
    this.isLoggedIn = this.authService.isLoggedIn();
    console.log(this.isLoggedIn);
    if (this.isLoggedIn) {
        this.userName = this.authService.getUserName();
       console.log(this.userName);
        this.personaldataService.findDataUser('https://servicios.espe.edu.ec:8443/UPBannerWS-0.0.1-SNAPSHOT/UPBannerWS/user/',this.userName).subscribe((data: {}) => {
          this.persona = data[0];
          this.personaldataService.findDataUser('https://servicios.espe.edu.ec:8443/miEspeRPWS-0.0.1-SNAPSHOT/restWs/userldap/',this.userName).subscribe(
            data =>{
              this.personaldataService.findDataUser('https://miespemovil.espe.edu.ec/reportes/reporteWs/cedulaById/',data.).subscribe(
                data =>{

                }
              )
            }
          )
          console.log('USUARIO', this.persona.pidm);
          this.initialiseInvites(this.persona.pidm);
        });

    }
    this.menuItems = ROUTES.filter(menuItem => menuItem);
    this.menuItems2 = ROUTESA.filter(menuItem => menuItem);
    this.menuItems3 = ROUTESR.filter(menuItem => menuItem);
    this.menuItems4 = ROUTEST.filter(menuItem => menuItem);

  }
  isMobileMenu() {
    if ($(window).width() > 991) {
      return false;
    }
    return true;
  };

  getmenu() {
    console.log(atob(localStorage.getItem('iduser')))
    if (localStorage.getItem('iduser')) {
        this.personaldataService.findDataUser(atob(localStorage.getItem('iduser'))).subscribe(
            data => {
                console.log(data)
                if (data.opciones) {
                    this.menuItems = Array.from(
                        new Set(data.opciones.map(x => x.opcion))
                    ).map(datos => {
                        return {
                            opcion: data.opciones.find(s => s.opcion === datos).opcion,
                            url: data.opciones.find(s => s.opcion === datos).url,
                            icono: data.opciones.find(s => s.opcion === datos).icono,
                            clase: data.opciones.find(s => s.opcion === datos).clase
                        };
                    });
                }this.router.navigate(['/mis-formularios']);
            },
            error => {
                console.log(error);
            }
        );

    }

  }
  initialiseInvites(upidm) {
    // Set default values and re-fetch any data you need.
    // localStorage.getItem('PID');
    // //console.log('pidm', btoa(upidm))
    localStorage.setItem('pidm', upidm);
    // localStorage.getItem('pidm')
  }
  // tipoUsuario() {

  //   this.restService.findDataById("tipoPersona/", this.spidem).subscribe(
  //     data => {
  //       this.usuario = data;
  //       console.log("El usuario",this.usuario)
  //       if (this.usuario == undefined) {
  //         console.log("El usuario no tiene permisos")
  //       }

  //     }
  //   )
  // }

  }


declare interface RouteInfo {
  path: string;
  title: string;
  icon: string;
  class: string;

}


ngOnInit() {
    this.isLoggedIn = this.authService.isLoggedIn();
    console.log(this.isLoggedIn);
    if (this.isLoggedIn) {
        this.userName = this.authService.getUserName();
       console.log(this.userName);
        this.personaldataService.findDataUser('https://servicios.espe.edu.ec:8443/UPBannerWS-0.0.1-SNAPSHOT/UPBannerWS/user/',this.userName).subscribe((data: {}) => {
          this.persona = data[0];
          this.personaldataService.findDataUser('https://servicios.espe.edu.ec:8443/miEspeRPWS-0.0.1-SNAPSHOT/restWs/userldap/',this.userName).subscribe(
            data =>{
              this.personaldataService.findDataUser('https://miespemovil.espe.edu.ec/reportes/reporteWs/cedulaById/',data.).subscribe(
                data =>{

                }
              )
            }
          )
          console.log('USUARIO', this.persona.pidm);
          this.initialiseInvites(this.persona.pidm);
        });

    }
    this.menuItems = ROUTES.filter(menuItem => menuItem);
    this.menuItems2 = ROUTESA.filter(menuItem => menuItem);
    this.menuItems3 = ROUTESR.filter(menuItem => menuItem);
    this.menuItems4 = ROUTEST.filter(menuItem => menuItem);

  }


getmenu() {
    console.log(atob(localStorage.getItem('iduser')))
    if (localStorage.getItem('iduser')) {
        this.personaldataService.findDataUser(atob(localStorage.getItem('iduser'))).subscribe(
            data => {
                console.log(data)
                if (data.opciones) {
                    this.menuItems = Array.from(
                        new Set(data.opciones.map(x => x.opcion))
                    ).map(datos => {
                        return {
                            opcion: data.opciones.find(s => s.opcion === datos).opcion,
                            url: data.opciones.find(s => s.opcion === datos).url,
                            icono: data.opciones.find(s => s.opcion === datos).icono,
                            clase: data.opciones.find(s => s.opcion === datos).clase
                        };
                    });
                }this.router.navigate(['/mis-formularios']);
            },
            error => {
                console.log(error);
            }
        );

    }

  }


initialiseInvites(upidm) {
    // Set default values and re-fetch any data you need.
    // localStorage.getItem('PID');
    // //console.log('pidm', btoa(upidm))
    localStorage.setItem('pidm', upidm);
    // localStorage.getItem('pidm')
  }


props => {
    const history = useHistory();

    const handlerSearch = (value: string) => {
        if (!value) {
            return;
        }
        history.push(`${GLOBAL_SEARCH_PAGE}?${SEARCH_KEY}=${value}`);
    };

    const prefixCls = getPrefixCls("landing-page");

    return (
        <EMonitorPage className={prefixCls}>
            <div className="logo-container">
                <EMonitorLogo
                    link="/"
                    dark={EMONITOR_LOGO_DARK}
                    light={EMONITOR_LOGO_LIGHT}
                />
            </div>

            <GlobalSearchBox
                size="large"
                style={{margin: "0 auto"}}


(value: string) => {
        if (!value) {
            return;
        }
        history.push(`${GLOBAL_SEARCH_PAGE}?${SEARCH_KEY}=${value}`);
    }


/**
 *
Updates a Stage.

 * @example
 * Use a bare-bones client and the command you need to make an API call.
 * ```javascript
 * import { ApiGatewayV2Client, UpdateStageCommand } from "@aws-sdk/client-apigatewayv2"; // ES Modules import
 * // const { ApiGatewayV2Client, UpdateStageCommand } = require("@aws-sdk/client-apigatewayv2"); // CommonJS import
 * const client = new ApiGatewayV2Client(config);
 * const command = new UpdateStageCommand(input);
 * const response = await client.send(command);
 * ```
 *
 * @see {@link UpdateStageCommandInput} for command's `input` shape.
 * @see {@link UpdateStageCommandOutput} for command's `response` shape.
 * @see {@link ApiGatewayV2ClientResolvedConfig | config} for command's `input` shape.
 *
 */
export class UpdateStageCommand extends $Command<
  UpdateStageCommandInput,
  UpdateStageCommandOutput,
  ApiGatewayV2ClientResolvedConfig
> {
  // Start section: command_properties
  // End section: command_properties

  constructor(readonly input: UpdateStageCommandInput) {
    // Start section: command_constructor
    super();
    // End section: command_constructor
  }

  /**
   * @internal
   */
  resolveMiddleware(
    clientStack: MiddlewareStack<ServiceInputTypes, ServiceOutputTypes>,
    configuration: ApiGatewayV2ClientResolvedConfig,
    options?: __HttpHandlerOptions
  ): Handler<UpdateStageCommandInput, UpdateStageCommandOutput> {
    this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize));

    const stack = clientStack.concat(this.middlewareStack);

    const { logger } = configuration;
    const clientName = "ApiGatewayV2Client";
    const commandName = "UpdateStageCommand";
    const handlerExecutionContext: HandlerExecutionContext = {
      logger,
      clientName,
      commandName,
      inputFilterSensitiveLog: UpdateStageRequest.filterSensitiveLog,
      outputFilterSensitiveLog: UpdateStageResponse.filterSensitiveLog,
    };
    const { requestHandler } = configuration;
    return stack.resolve(
      (request: FinalizeHandlerArguments<any>) =>
        requestHandler.handle(request.request as __HttpRequest, options || {}),
      handlerExecutionContext
    );
  }

  private serialize(input: UpdateStageCommandInput, context: __SerdeContext): Promise<__HttpRequest> {
    return serializeAws_restJson1UpdateStageCommand(input, context);
  }

  private deserialize(output: __HttpResponse, context: __SerdeContext): Promise<UpdateStageCommandOutput> {
    return deserializeAws_restJson1UpdateStageCommand(output, context);
  }

  // Start section: command_body_extra
  // End section: command_body_extra
}


export interface UpdateStageCommandInput extends UpdateStageRequest {}


export interface UpdateStageCommandOutput extends UpdateStageResponse, __MetadataBearer {}


/**
   * @internal
   */
resolveMiddleware(
    clientStack: MiddlewareStack<ServiceInputTypes, ServiceOutputTypes>,
    configuration: ApiGatewayV2ClientResolvedConfig,
    options?: __HttpHandlerOptions
  ): Handler<UpdateStageCommandInput, UpdateStageCommandOutput> {
    this.middlewareStack.use(getSerdePlugin(configuration, this.serialize, this.deserialize));

    const stack = clientStack.concat(this.middlewareStack);

    const { logger } = configuration;
    const clientName = "ApiGatewayV2Client";
    const commandName = "UpdateStageCommand";
    const handlerExecutionContext: HandlerExecutionContext = {
      logger,
      clientName,
      commandName,
      inputFilterSensitiveLog: UpdateStageRequest.filterSensitiveLog,
      outputFilterSensitiveLog: UpdateStageResponse.filterSensitiveLog,
    };
    const { requestHandler } = configuration;
    return stack.resolve(
      (request: FinalizeHandlerArguments<any>) =>
        requestHandler.handle(request.request as __HttpRequest, options || {}),
      handlerExecutionContext
    );
  }


private serialize(input: UpdateStageCommandInput, context: __SerdeContext): Promise<__HttpRequest> {
    return serializeAws_restJson1UpdateStageCommand(input, context);
  }


private deserialize(output: __HttpResponse, context: __SerdeContext): Promise<UpdateStageCommandOutput> {
    return deserializeAws_restJson1UpdateStageCommand(output, context);
  }


function isInRange(range: IRange, index: number): boolean {
  return range.start <= index && index < range.end;
}


(scrollTop: number) => {
      this._render(scrollTop);
    }


export class VirtualizedList<TItem extends IObjectWithKey> extends BaseComponent<IVirtualizedListProps<TItem>, IVirtualizedListState> {
  public static contextTypes: typeof ScrollContainerContextTypes = ScrollContainerContextTypes;
  public context: IScrollContainerContext;

  private _root: HTMLElement;

  private _spacerElements: { [key: string]: HTMLElement } = {};

  private _focusedIndex: number;

  constructor(props: IVirtualizedListProps<TItem>, context: IScrollContainerContext) {
    super(props, context);

    this._focusedIndex = -1;

    const {
      initialViewportHeight = window.innerHeight  // Start with the window height if not passed in props, this does not cause layout
    } = this.props;

    this.state = {
      viewportHeight: initialViewportHeight,
      items: this._renderItems(0, initialViewportHeight)
    };
  }

  public componentDidMount(): void {
    this._events.on(this._root, 'focus', this._onFocus, true);

    this.context.scrollContainer.registerVisibleCallback((scrollTop: number) => {
      this._render(scrollTop);
    });

    this.componentDidUpdate();
  }

  public componentDidUpdate(): void {
    // (Re-)register with the observer after every update, this way we'll get an intersection event immediately if one of the spacer
    // elements is visible right now.
    for (const key of Object.keys(this._spacerElements)) {
      const ref = this._spacerElements[key];
      this.context.scrollContainer.observe(ref);
    }
  }

  public componentWillUpdate(): void {
    for (const key of Object.keys(this._spacerElements)) {
      const ref = this._spacerElements[key];
      this.context.scrollContainer.unobserve(ref);
    }
  }

  public render(): JSX.Element {
    const { className } = this.props;
    const { items } = this.state;

    return (
      <div
        className={ css('ms-VirtualizedList', className) }
        ref={ this._resolveRef('_root') }
      >
        { items }
      </div>
    );
  }

  private _renderItems(scrollTop: number, viewportHeight: number): (JSX.Element | null)[] {
    const {
      itemHeight,
      items,
      itemOverdraw = 2
    } = this.props;

    let ranges: IRange[] = [];

    // Calculate visible range
    const startIndex = Math.floor(
      Math.max(
        scrollTop / itemHeight - itemOverdraw,
        0)
    );
    const endIndex = Math.floor(
      Math.min(
        startIndex + (itemOverdraw * 2) + (viewportHeight / itemHeight),
        items.length)
    );

    const visibleRange = {
      start: startIndex,
      end: endIndex
    };

    ranges.push(visibleRange);

    // Focused item
    if (this._focusedIndex !== -1 && !isInRange(visibleRange, this._focusedIndex)) {
      const focusRange: IRange = {
        start: this._focusedIndex,
        end: this._focusedIndex + 1
      };

      if (this._focusedIndex < visibleRange.start) {
        ranges.unshift(focusRange);
      } else {
        ranges.push(focusRange);
      }
    }

    return this._renderRanges(ranges);
  }

  private _renderRanges(ranges: IRange[]): (JSX.Element | null)[] {
    const { items, onRenderItem } = this.props;
    const result: (JSX.Element | null)[] = [];

    // Assume ranges are sorted.

    let lastRenderedIndex = -1;

    for (const range of ranges) {
      // Spacer item before range or between the last range and this one
      const isFirstRange = lastRenderedIndex === -1;
      if ((isFirstRange && range.start !== 0)
        || (!isFirstRange && lastRenderedIndex !== range.start)) {
        // Last range is not continuous with this one,
        // or the first range does not start from the beginning: insert spacer item
        const spacerStartIndex = (isFirstRange ? 0 : lastRenderedIndex);
        const gapBetweenRanges = range.start - spacerStartIndex;
        if (gapBetweenRanges > 0) {
          result.push(this._renderSpacerItem(gapBetweenRanges, spacerStartIndex));
        }
      }

      for (let i = range.start; i < range.end; ++i) {
        result.push(onRenderItem(items[i], i));
      }

      lastRenderedIndex = range.end - 1;
    }

    // Insert final spacer item
    const itemCount = (items || []).length;
    if (lastRenderedIndex < itemCount - 1) {
      result.push(this._renderSpacerItem(itemCount - lastRenderedIndex, lastRenderedIndex));
    }

    return result;
  }

  private _renderSpacerItem(numberOfItems: number, index: number): JSX.Element {
    const {
      itemHeight,
      items = [],
      spacerItemTagName: ItemTag = 'div'
    } = this.props;

    const spacerHeight = numberOfItems * itemHeight;
    const itemCount = items.length;

    let key: string;
    if (index === 0) {
      key = `spacer-start`;
    } else if (index + numberOfItems === itemCount) {
      key = `spacer-end`;
    } else {
      key = `spacer-item-${index + numberOfItems}`;
    }

    // tslint:disable-next-line:jsx-ban-props
    return <ItemTag ref={ this._spacerRef.bind(this, key) } key={ key } style={ { height: spacerHeight } }


interface IRange {
  /** Start of range */
  start: number;

  /** Exclusive end of range */
  end: number;
}


export interface IVirtualizedListState {
  viewportHeight: number;

  items: React.ReactNode[];
}


public componentDidMount(): void {
    this._events.on(this._root, 'focus', this._onFocus, true);

    this.context.scrollContainer.registerVisibleCallback((scrollTop: number) => {
      this._render(scrollTop);
    });

    this.componentDidUpdate();
  }


public componentDidUpdate(): void {
    // (Re-)register with the observer after every update, this way we'll get an intersection event immediately if one of the spacer
    // elements is visible right now.
    for (const key of Object.keys(this._spacerElements)) {
      const ref = this._spacerElements[key];
      this.context.scrollContainer.observe(ref);
    }
  }


public componentWillUpdate(): void {
    for (const key of Object.keys(this._spacerElements)) {
      const ref = this._spacerElements[key];
      this.context.scrollContainer.unobserve(ref);
    }
  }


public render(): JSX.Element {
    const { className } = this.props;
    const { items } = this.state;

    return (
      <div
        className={ css('ms-VirtualizedList', className) }
        ref={ this._resolveRef('_root') }
      >
        { items }
      </div>
    );
  }


css('ms-VirtualizedList', className)


private _renderItems(scrollTop: number, viewportHeight: number): (JSX.Element | null)[] {
    const {
      itemHeight,
      items,
      itemOverdraw = 2
    } = this.props;

    let ranges: IRange[] = [];

    // Calculate visible range
    const startIndex = Math.floor(
      Math.max(
        scrollTop / itemHeight - itemOverdraw,
        0)
    );
    const endIndex = Math.floor(
      Math.min(
        startIndex + (itemOverdraw * 2) + (viewportHeight / itemHeight),
        items.length)
    );

    const visibleRange = {
      start: startIndex,
      end: endIndex
    };

    ranges.push(visibleRange);

    // Focused item
    if (this._focusedIndex !== -1 && !isInRange(visibleRange, this._focusedIndex)) {
      const focusRange: IRange = {
        start: this._focusedIndex,
        end: this._focusedIndex + 1
      };

      if (this._focusedIndex < visibleRange.start) {
        ranges.unshift(focusRange);
      } else {
        ranges.push(focusRange);
      }
    }

    return this._renderRanges(ranges);
  }


private _renderRanges(ranges: IRange[]): (JSX.Element | null)[] {
    const { items, onRenderItem } = this.props;
    const result: (JSX.Element | null)[] = [];

    // Assume ranges are sorted.

    let lastRenderedIndex = -1;

    for (const range of ranges) {
      // Spacer item before range or between the last range and this one
      const isFirstRange = lastRenderedIndex === -1;
      if ((isFirstRange && range.start !== 0)
        || (!isFirstRange && lastRenderedIndex !== range.start)) {
        // Last range is not continuous with this one,
        // or the first range does not start from the beginning: insert spacer item
        const spacerStartIndex = (isFirstRange ? 0 : lastRenderedIndex);
        const gapBetweenRanges = range.start - spacerStartIndex;
        if (gapBetweenRanges > 0) {
          result.push(this._renderSpacerItem(gapBetweenRanges, spacerStartIndex));
        }
      }

      for (let i = range.start; i < range.end; ++i) {
        result.push(onRenderItem(items[i], i));
      }

      lastRenderedIndex = range.end - 1;
    }

    // Insert final spacer item
    const itemCount = (items || []).length;
    if (lastRenderedIndex < itemCount - 1) {
      result.push(this._renderSpacerItem(itemCount - lastRenderedIndex, lastRenderedIndex));
    }

    return result;
  }


private _renderSpacerItem(numberOfItems: number, index: number): JSX.Element {
    const {
      itemHeight,
      items = [],
      spacerItemTagName: ItemTag = 'div'
    } = this.props;

    const spacerHeight = numberOfItems * itemHeight;
    const itemCount = items.length;

    let key: string;
    if (index === 0) {
      key = `spacer-start`;
    } else if (index + numberOfItems === itemCount) {
      key = `spacer-end`;
    } else {
      key = `spacer-item-${index + numberOfItems}`;
    }

    // tslint:disable-next-line:jsx-ban-props
    return <ItemTag ref={ this._spacerRef.bind(this, key) } key={ key } style={ { height: spacerHeight } }


if (ref) {
      this._spacerElements[key] = ref;
    }


while (target


@Module({
  providers: [UserService, UserResolver],
  exports: [UserService],
})
export class UserModule {}


function plural(n: number): number {
  let i = Math.floor(Math.abs(n));
  if (i === 0 || i === 1) return 1;
  return 5;
}


function* IdGenerator(prefix: string): IterableIterator<string> {
  let number = 1;
  let pre = prefix;
  while (true) {
    yield `${pre}-${number}`;
    if (number == Number.MAX_SAFE_INTEGER - 1) {
      number = 0;
      pre += "x";
    }
    number++;
  }
}


getId(this: any): string {
      return idGenerator.next().value;
    }


() => {
  it('should work', async () => {
    await initLogService();
  });
}


async () => {
    await initLogService();
  }


public async fullGeneration(): Promise<string[]> {
        // return this.render();
        return this.GenerateAzureCliReport(this.model);
    }


public async incrementalGeneration(base: string): Promise<string[]> {
        return await this.fullGeneration();
    }


public GetRenderData(model: CodeModelAz): any {
        let data = {};

        const converter = new Map<string, (item) => unknown>([
            [
                'mapsTo',
                function (item: string) {
                    if (item.endsWith('_')) {
                        item = item.substr(0, item.length - 1);
                    }
                    item = item.replace(/_/g, '-');
                    return item;
                },
            ],
        ]);

        const inputProperties: Map<CodeModelTypes, RenderInput> = new Map<
            CodeModelTypes,
            RenderInput
        >([
            ['extension', new RenderInput(['name'], { name: SortOrder.ASEC })],
            ['commandGroup', new RenderInput(['name', 'cliKey'], { name: SortOrder.ASEC })],
            ['command', new RenderInput(['name'])],
            ['method', new RenderInput(['nameAz', 'cliKey'], { nameAz: SortOrder.ASEC })],
            [
                'methodParameter',
                new RenderInput(
                    ['mapsTo', 'type', 'description', 'cliKey', 'namePython'],
                    {},
                    [
                        ['isFlattened', true],
                        ['type', SchemaType.Constant],
                        ['isPolyOfSimple', true],
                        ['isDiscriminator', true],
                    ],
                    converter,
                ),
            ],
            ['azExample', new RenderInput(['commandStringItems'], {})],
        ]);

        const dependencies = <[CodeModelTypes, CodeModelTypes][]>[
            ['extension', 'commandGroup'],
            ['commandGroup', 'command'],
            ['command', 'method'],
            ['method', 'methodParameter'],
            ['method', 'azExample'],
        ];
        data = model.getModelData('extension', inputProperties, dependencies);
        return data;
    }


GenerateAzureCliReport(model: CodeModelAz): string[] {
        let output: string[] = [];

        output.push('# Azure CLI Module Creation Report');
        output.push('');
        output.push('## EXTENSION');
        output.push('|CLI Extension|Command Groups|');
        output.push('|---------|------------|');
        output.push('|az ' + model.Extension_Name + '|[groups](#CommandGroups)');
        output.push('');
        output.push('## GROUPS');
        output.push(
            '### <a name="CommandGroups">Command groups in `az ' +
                model.Extension_Name +
                '` extension </a>',
        );
        output.push('|CLI Command Group|Group Swagger name|Commands|');
        output.push('|---------|------------|--------|');

        let cmds = {};
        if (model.SelectFirstCommandGroup()) {
            do {
                output.push(
                    '|az ' +
                        model.CommandGroup_Name +
                        '|' +
                        model.CommandGroup_CliKey +
                        '|' +
                        '[commands](#CommandsIn' +
                        model.CommandGroup_CliKey +
                        ')|',
                );
            } while (model.SelectNextCommandGroup());
        }

        output.push('');
        output.push('## COMMANDS');

        if (model.SelectFirstCommandGroup()) {
            let mo: string[] = [];
            do {
                if (model.SelectFirstCommand()) {
                    mo = this.getCommandBody(model);
                    if (!isNullOrUndefined(cmds[model.CommandGroup_Name])) {
                        cmds[model.CommandGroup_Name] = cmds[model.CommandGroup_Name].concat(mo);
                    } else {
                        cmds[model.CommandGroup_Name] = mo;
                    }
                }
            } while (model.SelectNextCommandGroup());
        }

        // build sorted output
        let keys = Object.keys(cmds);
        keys.sort();

        for (let i = 0; i < keys.length; i++) {
            output = output.concat(cmds[keys[i]]);
        }

        output.push('');
        cmds = {};
        output.push('## COMMAND DETAILS');
        output.push('');

        if (model.SelectFirstCommandGroup()) {
            let mo: string[] = [];
            do {
                if (model.SelectFirstCommand()) {
                    mo = this.getCommandDetails(model);
                    if (!isNullOrUndefined(cmds[model.CommandGroup_Name])) {
                        cmds[model.CommandGroup_Name] = cmds[model.CommandGroup_Name].concat(mo);
                    } else {
                        cmds[model.CommandGroup_Name] = mo;
                    }
                }
            } while (model.SelectNextCommandGroup());
        }
        keys = Object.keys(cmds);
        keys.sort();

        for (let i = 0; i < keys.length; i++) {
            output = output.concat(cmds[keys[i]]);
        }
        return output;
    }


getCommandBody(model: CodeModelAz) {
        const mo: string[] = [];
        mo.push(
            '### Commands in `az ' +
                model.CommandGroup_Name +
                '` group',
        );
        mo.push('|CLI Command|Operation Swagger name|Parameters|Examples|');
        mo.push('|---------|------------|--------|-----------|');
        if (model.SelectFirstCommand()) {
            do {
                if (model.SelectFirstMethod()) {
                    do {
                        if (model.GetExamples().length > 0) {
                            mo.push(
                                '|[az ' +
                                    model.CommandGroup_Name +
                                    ' ' +
                                    model.Method_NameAz +
                                    '](#' +
                                    model.CommandGroup_CliKey +
                                    model.Method_CliKey +
                                    ')|' +
                                    model.Method_CliKey +
                                    '|' +
                                    '[Parameters](#Parameters' +
                                    model.CommandGroup_CliKey +
                                    model.Method_CliKey +
                                    ')' +
                                    '|' +
                                    '[Example](#Examples' +
                                    model.CommandGroup_CliKey +
                                    model.Method_CliKey +
                                    ')|',
                            );
                        } else {
                            mo.push(
                                '|[az ' +
                                    model.CommandGroup_Name +
                                    ' ' +
                                    model.Method_NameAz +
                                    '](#' +
                                    model.CommandGroup_CliKey +
                                    model.Method_CliKey +
                                    ')|' +
                                    model.Method_CliKey +
                                    '|' +
                                    '[Parameters](#Parameters' +
                                    model.CommandGroup_CliKey +
                                    model.Method_CliKey +
                                    ')' +
                                    '|Not Found|',
                            );
                        }
                    } while (model.SelectNextMethod());
                }
            } while (model.SelectNextCommand());
        }
        mo.push('');
        return mo;
    }


getCommandDetails(model: CodeModelAz) {
        let mo: string[] = [];
        mo.push('### group `az ' + model.CommandGroup_Name + '`');
        if (model.SelectFirstCommand()) {
            do {
                const allRequiredParam: Map<string, boolean> = new Map<string, boolean>();
                const allNonRequiredParam: Map<string, boolean> = new Map<string, boolean>();
                let requiredmo: Array<string> = [];
                let nonrequiredmo: Array<string> = [];
                if (model.SelectFirstMethod()) {
                    do {
                        mo.push(
                            '#### Command `az ' +
                                model.CommandGroup_Name +
                                ' ' +
                                model.Method_NameAz +
                                '`',
                        );
                        mo.push('');
                        for (const example of model.GetExamples()) {
                            mo.push(
                                '##### Example',
                            );
                            mo.push('```');
                            let parameters: string[] = [];
                            parameters = model.GetExampleItems(example, false, undefined);
                            const line = parameters.join(' ');
                            ToMultiLine(line, mo, CodeGenConstants.PYLINT_MAX_CODE_LENGTH, true);
                            mo.push('```');
                        }
                        mo.push(
                            '##### Parameters ',
                        );
                        mo.push('|Option|Type|Description|Path (SDK)|Swagger name|');
                        mo.push('|------|----|-----------|----------|------------|');
                        if (!model.SelectFirstMethodParameter()) {
                            continue;
                        }
                        const originalOperation = model.Method_GetOriginalOperation;
                        do {
                            if (
                                model.MethodParameter_IsFlattened ||
                                model.MethodParameter_Type === SchemaType.Constant
                            ) {
                                continue;
                            }
                            if (model.Parameter_IsPolyOfSimple(model.MethodParameter)) {
                                continue;
                            }
                            if (
                                !isNullOrUndefined(originalOperation) &&
                                model.MethodParameter['targetProperty']?.isDiscriminator
                            ) {
                                continue;
                            }
                            let optionName = model.MethodParameter_MapsTo;
                            if (optionName.endsWith('_')) {
                                optionName = optionName.substr(0, optionName.length - 1);
                            }
                            optionName = optionName.replace(/_/g, '-');
                            if (model.MethodParameter_IsRequired) {
                                if (allRequiredParam.has(optionName)) {
                                    continue;
                                }
                                allRequiredParam.set(optionName, true);
                                requiredmo.push(
                                    '|**--' +
                                        optionName +
                                        '**|' +
                                        model.MethodParameter_Type +
                                        '|' +
                                        model.MethodParameter_Description +
                                        '|' +
                                        model.MethodParameter_Name +
                                        '|' +
                                        model.MethodParameter_CliKey +
                                        '|',
                                );
                            } else {
                                if (allNonRequiredParam.has(optionName)) {
                                    continue;
                                }
                                allNonRequiredParam.set(optionName, true);
                                nonrequiredmo.push(
                                    '|**--' +
                                        optionName +
                                        '**|' +
                                        model.MethodParameter_Type +
                                        '|' +
                                        model.MethodParameter_Description +
                                        '|' +
                                        model.MethodParameter_Name +
                                        '|' +
                                        model.MethodParameter_CliKey +
                                        '|',
                                );
                            }
                        } while (model.SelectNextMethodParameter());
                        let flag = false;
                        if (requiredmo.length > 0 || nonrequiredmo.length > 0) {
                            flag = true;
                        }
                        if (requiredmo.length > 0) {
                            mo = mo.concat(requiredmo);
                            requiredmo = [];
                        }
                        if (nonrequiredmo.length > 0) {
                            mo = mo.concat(nonrequiredmo);
                            nonrequiredmo = [];
                        }
                        if (flag) mo.push('');
                    } while (model.SelectNextMethod());
                }
                if (requiredmo.length <= 0 && nonrequiredmo.length < 0) {
                    return mo;
                }
            } while (model.SelectNextCommand());
        }
        return mo;
    }


export class ParentingPropertyGridComponent extends React.Component<IParentingPropertyGridComponentProps> {
    constructor(props: IParentingPropertyGridComponentProps) {
        super(props);
    }
    private _columnNumber: number;
    private _rowNumber: number;

    updateGridPosition() {
        const grid = this.props.control.parent as Grid;
        if (grid) {
            this._changeCell(grid, this.props.control, new Vector2(this._columnNumber, this._rowNumber));
        }
    }

    getCellInfo() {
        const cellInfo = Tools.getCellInfo(this.props.control.parent as Grid, this.props.control);
        this._columnNumber = cellInfo.x;
        this._rowNumber = cellInfo.y;
    }

    private _changeCell(grid: Grid, draggedControl: Control, newCell : Vector2) {
        let index = grid.children.indexOf(draggedControl);
        grid.removeControl(draggedControl);
        Tools.reorderGrid(grid, index, draggedControl,newCell);
    }

    render() {
        this.getCellInfo();
        return (

                <TextLineComponent tooltip="" label="GRID PARENTING" value=" " color="grey"></TextLineComponent>

                    <FloatLineComponent label={"Row #"} target={this} propertyName={"_rowNumber"} isInteger={true} min={0} onPropertyChangedObservable={this.props.onPropertyChangedObservable}
                        onChange={(newValue) => {
                            this.updateGridPosition();
                        }}


interface IParentingPropertyGridComponentProps {
    control: Control,
    lockObject: LockObject,
    onPropertyChangedObservable?: Observable<PropertyChangedEvent>
}


updateGridPosition() {
        const grid = this.props.control.parent as Grid;
        if (grid) {
            this._changeCell(grid, this.props.control, new Vector2(this._columnNumber, this._rowNumber));
        }
    }


getCellInfo() {
        const cellInfo = Tools.getCellInfo(this.props.control.parent as Grid, this.props.control);
        this._columnNumber = cellInfo.x;
        this._rowNumber = cellInfo.y;
    }


private _changeCell(grid: Grid, draggedControl: Control, newCell : Vector2) {
        let index = grid.children.indexOf(draggedControl);
        grid.removeControl(draggedControl);
        Tools.reorderGrid(grid, index, draggedControl,newCell);
    }


render() {
        this.getCellInfo();
        return (

                <TextLineComponent tooltip="" label="GRID PARENTING" value=" " color="grey"></TextLineComponent>

                    <FloatLineComponent label={"Row #"} target={this} propertyName={"_rowNumber"} isInteger={true} min={0} onPropertyChangedObservable={this.props.onPropertyChangedObservable}
                        onChange={(newValue) => {
                            this.updateGridPosition();
                        }}


(
    {
      as: Component = 'div',
      style,
      className,
      classPrefix,
      visible,
      layer,
      disabled,
      allUncheckable,
      rtl,
      loading,
      expand,
      hasChildren,
      nodeData,
      focus,
      label,
      uncheckable,
      checkState,
      onExpand,
      onSelect,
      onRenderTreeIcon,
      onRenderTreeNode
    },
    ref
  ) => {
    const { prefix, merge, withClassPrefix } = useClassNames(classPrefix);

    const getTitle = () => {
      if (typeof label === 'string') {
        return label;
      } else if (React.isValidElement(label)) {
        const nodes = reactToString(label);
        return nodes.join('');
      }
    };

    const handleExpand = useCallback(
      (event: React.SyntheticEvent<any>) => {
        // stop propagation when using custom loading icon
        event?.nativeEvent?.stopImmediatePropagation?.();
        onExpand?.(nodeData);
      },
      [nodeData, onExpand]
    );

    const handleSelect = useCallback(
      (_value: any, event: React.SyntheticEvent<any>) => {
        if (disabled || uncheckable) {
          return;
        }

        let isChecked = false;
        if (checkState === CHECK_STATE.UNCHECK || checkState === CHECK_STATE.INDETERMINATE) {
          isChecked = true;
        }

        if (checkState === CHECK_STATE.CHECK) {
          isChecked = false;
        }

        const nextNodeData = {
          ...nodeData,
          check: isChecked
        };
        onSelect?.(nextNodeData, event);
      },
      [disabled, checkState, uncheckable, nodeData, onSelect]
    );

    const renderIcon = () => {
      const expandIconClasses = prefix('expand-icon', 'icon', {
        expanded: expand
      });

      let expandIcon = <i className={expandIconClasses} />;

      if (loading) {
        expandIcon = (
          <div className={prefix('loading-icon')}>
            <Icon icon="spinner" spin style={{ verticalAlign: 'middle' }} />
          </div>


() => {
      if (typeof label === 'string') {
        return label;
      } else if (React.isValidElement(label)) {
        const nodes = reactToString(label);
        return nodes.join('');
      }
    }


(event: React.SyntheticEvent<any>) => {
        // stop propagation when using custom loading icon
        event?.nativeEvent?.stopImmediatePropagation?.();
        onExpand?.(nodeData);
      }


(_value: any, event: React.SyntheticEvent<any>) => {
        if (disabled || uncheckable) {
          return;
        }

        let isChecked = false;
        if (checkState === CHECK_STATE.UNCHECK || checkState === CHECK_STATE.INDETERMINATE) {
          isChecked = true;
        }

        if (checkState === CHECK_STATE.CHECK) {
          isChecked = false;
        }

        const nextNodeData = {
          ...nodeData,
          check: isChecked
        };
        onSelect?.(nextNodeData, event);
      }


() => {
      const expandIconClasses = prefix('expand-icon', 'icon', {
        expanded: expand
      });

      let expandIcon = <i className={expandIconClasses} />;

      if (loading) {
        expandIcon = (
          <div className={prefix('loading-icon')}>
            <Icon icon="spinner" spin style={{ verticalAlign: 'middle' }} />
          </div>


() => {
      return (
        <DropdownMenuCheckItem
          as="div"
          active={checkState === CHECK_STATE.CHECK}


export interface CheckTreeNodeProps extends WithAsProps {
  rtl?: boolean;
  label?: any;
  layer?: number;
  value?: any;
  focus?: boolean;
  style?: React.CSSProperties;
  expand?: boolean;
  loading?: boolean;
  visible?: boolean;
  nodeData?: any;
  disabled?: boolean;
  className?: string;
  checkState?: CheckStateType;
  classPrefix?: string;
  hasChildren?: boolean;
  uncheckable?: boolean;
  allUncheckable?: boolean;
  onExpand?: (nodeData: any) => void;
  onSelect?: (nodeData: any, event: React.SyntheticEvent<any>) => void;
  onRenderTreeIcon?: (nodeData: any, expandIcon?: React.ReactNode) => React.ReactNode;
  onRenderTreeNode?: (nodeData: any) => React.ReactNode;
}


prefix('loading-icon')


prefix('custom-icon')


prefix('expand-icon-wrapper')


prefix('label')


getTitle()


renderIcon()


({showNavMenu}: NavContainerProps) => showNavMenu ? 0 : -359


({selected}: CategoryProps) => selected ? 'background-color: lightgrey;' : ''


({ storeEndpoint, showNavMenu, setShowNavMenu }: Props) => {
  const location = useLocation();

  const categories = [
    {
      icon: 'home',
      name: 'Home',
      route: '/admin',
    },
    {
      icon: 'pricetag',
      name: 'Products',
      route: '/admin/products',
    },
    {
      icon: '',
      name: 'Add product',
      route: '/admin/products/new',
    },
    {
      icon: 'albums',
      name: 'Collections',
      route: '/admin/collections',
    },
    {
      icon: '',
      name: 'Create Collection',
      route: '/admin/collections/new',
    }
  ];

  return (
    <Container>
      {
        showNavMenu &&
        <DarkOverlay onClick={()


category => {
            return (
              <CategoryContainer key={category.name}>
                <Category
                  to={category.route}
                  selected={location.pathname === category.route}
                  onClick={() => setShowNavMenu(false)}


type NavContainerProps = {
  showNavMenu: boolean
};


type CategoryProps = {
  selected?: boolean
}


type Props = {
  storeEndpoint: string
  showNavMenu: boolean
  setShowNavMenu: React.Dispatch<React.SetStateAction<boolean>>
}


() => {
        let app: INestApplication;
        let repository: ExtendRepository<User>;
        let user: User;

        beforeAll(async () => {
                const module: TestingModule = await Test.createTestingModule({
                        imports: [...conInit(), TypeOrmModule.forFeature([UserRepository])],
                        providers: [FakeResolver],
                }).compile();

                app = module.createNestApplication();
                app.use(getInitMiddleware());
                await app.init();

                repository = module.get<UserRepository>(UserRepository);
        });

        //setup database
        beforeAll(async () => {
                user = await getUserInstance().save();
        });

        it('fake resolver', async () => {
                const { body } = await request(app.getHttpServer())
                        .post('/api/graphql')
                        .send({ query: `query{test}` });
                expect(body).toBeDefined();
        });

        it('should be defined', () => {
                expect(repository).toBeDefined();
        });

        describe('findOneById', () => {
                it('should return value', async () => {
                        const getUser = await repository.findOneById(user._id);
                        expect(getUser).toBeDefined();
                });
                it('should error with invalid id', async () => {
                        try {
                                await repository.findOneById('dsadsa213');
                        } catch (err) {
                                expect(err).toBeDefined();
                        }
                });
                it('should error with id does not exist', async () => {
                        const getUser = await repository.findOneById(new ObjectId());
                        expect(getUser).toBeUndefined();
                });
        });

        describe('findOneByField', () => {
                it('should return value', async () => {
                        const getUser = await repository.findOneByField('username', user.username);
                        expect(getUser).toBeDefined();
                });

                it('should error with invalid input', async () => {
                        const getUser = await repository.findOneByField('username', user.password);
                        expect(getUser).toBeUndefined();
                });
        });

        describe('isExist', () => {
                it('should return value', async () => {
                        const getUser = await repository.isExist('username', user.username);
                        expect(getUser).toBe(true);
                });

                it('should return value with id', async () => {
                        const getUser = await repository.isExist('_id', new ObjectId(user._id));
                        expect(getUser).toBe(true);
                });
                it('should return error with invalid input', async () => {
                        const getUser = await repository.isExist('username', user.password);
                        expect(getUser).toBe(false);
                });
        });

        describe('findManyByIds', () => {
                let ids;
                beforeAll(async () => {
                        await getUserInstance().save();
                        await getUserInstance().save();
                        await getUserInstance().save();

                        ids = await repository.find();
                        ids = ids.map(item => item._id);
                });
                it('should return array value', async () => {
                        const arr = await repository.findManyByIds(ids);
                        expect(arr.length).toBeGreaterThanOrEqual(3);
                });
        });

        afterAll(async () => {
                await repository.clear();
                await app.close();
        });
}


async () => {
                const module: TestingModule = await Test.createTestingModule({
                        imports: [...conInit(), TypeOrmModule.forFeature([UserRepository])],
                        providers: [FakeResolver],
                }).compile();

                app = module.createNestApplication();
                app.use(getInitMiddleware());
                await app.init();

                repository = module.get<UserRepository>(UserRepository);
        }


async () => {
                user = await getUserInstance().save();
        }


async () => {
                const { body } = await request(app.getHttpServer())
                        .post('/api/graphql')
                        .send({ query: `query{test}` });
                expect(body).toBeDefined();
        }


() => {
                expect(repository).toBeDefined();
        }


() => {
                it('should return value', async () => {
                        const getUser = await repository.findOneById(user._id);
                        expect(getUser).toBeDefined();
                });
                it('should error with invalid id', async () => {
                        try {
                                await repository.findOneById('dsadsa213');
                        } catch (err) {
                                expect(err).toBeDefined();
                        }
                });
                it('should error with id does not exist', async () => {
                        const getUser = await repository.findOneById(new ObjectId());
                        expect(getUser).toBeUndefined();
                });
        }


async () => {
                        const getUser = await repository.findOneById(user._id);
                        expect(getUser).toBeDefined();
                }


async () => {
                        try {
                                await repository.findOneById('dsadsa213');
                        } catch (err) {
                                expect(err).toBeDefined();
                        }
                }


async () => {
                        const getUser = await repository.findOneById(new ObjectId());
                        expect(getUser).toBeUndefined();
                }


() => {
                it('should return value', async () => {
                        const getUser = await repository.findOneByField('username', user.username);
                        expect(getUser).toBeDefined();
                });

                it('should error with invalid input', async () => {
                        const getUser = await repository.findOneByField('username', user.password);
                        expect(getUser).toBeUndefined();
                });
        }


async () => {
                        const getUser = await repository.findOneByField('username', user.username);
                        expect(getUser).toBeDefined();
                }


async () => {
                        const getUser = await repository.findOneByField('username', user.password);
                        expect(getUser).toBeUndefined();
                }


() => {
                it('should return value', async () => {
                        const getUser = await repository.isExist('username', user.username);
                        expect(getUser).toBe(true);
                });

                it('should return value with id', async () => {
                        const getUser = await repository.isExist('_id', new ObjectId(user._id));
                        expect(getUser).toBe(true);
                });
                it('should return error with invalid input', async () => {
                        const getUser = await repository.isExist('username', user.password);
                        expect(getUser).toBe(false);
                });
        }


async () => {
                        const getUser = await repository.isExist('username', user.username);
                        expect(getUser).toBe(true);
                }


async () => {
                        const getUser = await repository.isExist('_id', new ObjectId(user._id));
                        expect(getUser).toBe(true);
                }


async () => {
                        const getUser = await repository.isExist('username', user.password);
                        expect(getUser).toBe(false);
                }


() => {
                let ids;
                beforeAll(async () => {
                        await getUserInstance().save();
                        await getUserInstance().save();
                        await getUserInstance().save();

                        ids = await repository.find();
                        ids = ids.map(item => item._id);
                });
                it('should return array value', async () => {
                        const arr = await repository.findManyByIds(ids);
                        expect(arr.length).toBeGreaterThanOrEqual(3);
                });
        }


async () => {
                        await getUserInstance().save();
                        await getUserInstance().save();
                        await getUserInstance().save();

                        ids = await repository.find();
                        ids = ids.map(item => item._id);
                }


item => item._id


async () => {
                        const arr = await repository.findManyByIds(ids);
                        expect(arr.length).toBeGreaterThanOrEqual(3);
                }


async () => {
                await repository.clear();
                await app.close();
        }


(light, dark) => useColorModeValue(light, dark)


(color, amount) => whiten(color, amount)


(color, amount) => darken(color, amount)


(values) => useBreakpointValue(values)


() => ({
    sessionId: 'a',
    record: true,
    eventCount: 1
})


() => 'b'


() => ({
    SessionManager: jest.fn().mockImplementation(() => ({
        getSession,
        getUserId,
        getAttributes,
        incrementSessionEventCount
    }))
})


() => ({
        getSession,
        getUserId,
        getAttributes,
        incrementSessionEventCount
    })


() => {
        advanceTo(0);
    }


() => {
        getSession.mockClear();
        getUserId.mockClear();
        incrementSessionEventCount.mockClear();
    }


async () => {
        // Init
        const EVENT1_SCHEMA = 'com.amazon.rum.event1';
        const eventCache: EventCache = Utils.createDefaultEventCache();

        // Run
        eventCache.getEventBatch();
        eventCache.disable();
        eventCache.recordEvent(EVENT1_SCHEMA, {});

        // Assert
        expect(eventCache.hasEvents()).toBeFalsy();
    }


async () => {
        // Init
        const EVENT1_SCHEMA = 'com.amazon.rum.event1';
        const eventCache: EventCache = Utils.createDefaultEventCache();

        // Run
        eventCache.disable();
        eventCache.enable();
        eventCache.recordEvent(EVENT1_SCHEMA, {});

        // Assert
        expect(eventCache.hasEvents()).toBeTruthy();
    }


async () => {
        // Init
        const EVENT1_SCHEMA = 'com.amazon.rum.event1';
        const EVENT2_SCHEMA = 'com.amazon.rum.event2';
        const eventCache: EventCache = Utils.createDefaultEventCache();

        // Run
        eventCache.recordEvent(EVENT1_SCHEMA, {});
        eventCache.recordEvent(EVENT2_SCHEMA, {});

        // Assert
        expect(eventCache.hasEvents()).toBeTruthy();
        eventCache.getEventBatch();
        expect(eventCache.hasEvents()).toBeFalsy();
    }


async () => {
        // Init
        const EVENT1_SCHEMA = 'com.amazon.rum.event1';
        const EVENT2_SCHEMA = 'com.amazon.rum.event2';
        const eventCache: EventCache = Utils.createDefaultEventCache();
        const expectedEvents: RumEvent[] = [
            {
                id: expect.stringMatching(/[0-9a-f\-]+/),
                timestamp: new Date(),
                type: EVENT1_SCHEMA,
                metadata: '{"version":"1.0.0"}',
                details: '{}'
            },
            {
                id: expect.stringMatching(/[0-9a-f\-]+/),
                timestamp: new Date(),
                type: EVENT2_SCHEMA,
                metadata: '{"version":"1.0.0"}',
                details: '{}'
            }
        ];

        // Run
        eventCache.recordEvent(EVENT1_SCHEMA, {});
        eventCache.recordEvent(EVENT2_SCHEMA, {});
        const eventBatch: RumEvent[] = eventCache.getEventBatch();

        // Assert
        expect(eventBatch).toEqual(expect.arrayContaining(expectedEvents));
    }


async () => {
        // Init
        const EVENT1_SCHEMA = 'com.amazon.rum.event1';
        const EVENT2_SCHEMA = 'com.amazon.rum.event2';
        const BATCH_LIMIT = 1;
        const eventCache: EventCache = Utils.createEventCache({
            ...DEFAULT_CONFIG,
            ...{ batchLimit: BATCH_LIMIT }
        });

        // Run
        eventCache.recordEvent(EVENT1_SCHEMA, {});
        eventCache.recordEvent(EVENT2_SCHEMA, {});

        // Assert
        expect(eventCache.getEventBatch().length).toEqual(BATCH_LIMIT);
        expect(eventCache.getEventBatch().length).toEqual(BATCH_LIMIT);
        expect(eventCache.getEventBatch().length).toEqual(0);
    }


async () => {
        // Init
        const EVENT1_SCHEMA = 'com.amazon.rum.event1';
        const EVENT2_SCHEMA = 'com.amazon.rum.event2';
        const BATCH_LIMIT = 1;
        const eventCache: EventCache = Utils.createEventCache({
            ...DEFAULT_CONFIG,
            ...{ batchLimit: BATCH_LIMIT }
        });

        // Run
        eventCache.recordEvent(EVENT1_SCHEMA, {});
        eventCache.recordEvent(EVENT2_SCHEMA, {});

        // Assert
        expect(eventCache.getEventBatch()[0].type).toEqual(EVENT1_SCHEMA);
        expect(eventCache.getEventBatch()[0].type).toEqual(EVENT2_SCHEMA);
    }


async () => {
        // Init
        const EVENT1_SCHEMA = 'com.amazon.rum.event1';
        const EVENT2_SCHEMA = 'com.amazon.rum.event2';
        const BATCH_LIMIT = 20;
        const EVENT_LIMIT = 2;
        const eventCache: EventCache = Utils.createEventCache({
            ...DEFAULT_CONFIG,
            ...{
                batchLimit: BATCH_LIMIT,
                eventCacheSize: EVENT_LIMIT
            }
        });
        const expectedEvents: RumEvent[] = [
            {
                id: expect.stringMatching(/[0-9a-f\-]+/),
                timestamp: new Date(),
                type: EVENT2_SCHEMA,
                metadata: '{"version":"1.0.0"}',
                details: '{}'
            }
        ];

        // Run
        eventCache.recordEvent(EVENT1_SCHEMA, {});
        eventCache.recordEvent(EVENT2_SCHEMA, {});

        // Assert
        expect(await eventCache.getEventBatch()).toEqual(
            expect.arrayContaining(expectedEvents)
        );
        expect(eventCache.hasEvents()).toBeFalsy();
    }


async () => {
        // Init
        const EVENT1_SCHEMA = 'com.amazon.rum.event1';
        const eventCache: EventCache = Utils.createEventCache({
            ...DEFAULT_CONFIG,
            ...{
                pagesToExclude: [/.*/]
            }
        });

        // Run
        eventCache.recordEvent(EVENT1_SCHEMA, {});

        // Assert
        expect(eventCache.hasEvents()).toBeFalsy();
    }


async () => {
        // Init
        const EVENT1_SCHEMA = 'com.amazon.rum.event1';
        const eventCache: EventCache = Utils.createEventCache({
            ...DEFAULT_CONFIG,
            ...{
                pagesToInclude: [/.*/]
            }
        });
        const expectedEvents: RumEvent[] = [
            {
                id: expect.stringMatching(/[0-9a-f\-]+/),
                timestamp: new Date(),
                type: EVENT1_SCHEMA,
                metadata: '{"version":"1.0.0"}',
                details: '{}'
            }
        ];

        // Run
        eventCache.recordEvent(EVENT1_SCHEMA, {});

        // Assert
        expect(await eventCache.getEventBatch()).toEqual(
            expect.arrayContaining(expectedEvents)
        );
    }


async () => {
        // Init
        const EVENT1_SCHEMA = 'com.amazon.rum.event1';
        const eventCache: EventCache = Utils.createEventCache({
            ...DEFAULT_CONFIG,
            ...{
                pagesToInclude: [/.*/],
                pagesToExclude: [/.*/]
            }
        });

        // Run
        eventCache.recordEvent(EVENT1_SCHEMA, {});

        // Assert
        expect(eventCache.hasEvents()).toBeFalsy();
    }


async () => {
        // Init
        const getSession = jest.fn(() => ({ sessionId: 'a', record: true }));
        const getUserId = jest.fn(() => 'b');
        const incrementSessionEventCount = jest.fn();
        (SessionManager as any).mockImplementation(() => ({
            getSession,
            getUserId,
            incrementSessionEventCount
        }));

        const EVENT1_SCHEMA = 'com.amazon.rum.event1';
        const eventCache: EventCache = Utils.createDefaultEventCache();

        // Run
        eventCache.getEventBatch();
        eventCache.recordEvent(EVENT1_SCHEMA, {});

        // Assert
        expect(eventCache.hasEvents()).toBeFalsy();
    }


() => ({ sessionId: 'a', record: true })


() => ({
            getSession,
            getUserId,
            incrementSessionEventCount
        })


async () => {
        // Init
        const getSession = jest.fn(() => ({
            sessionId: 'a',
            record: true,
            eventCount: 1
        }));
        const getUserId = jest.fn(() => 'b');
        const getAttributes = jest.fn(() => {});
        const incrementSessionEventCount = jest.fn();
        (SessionManager as any).mockImplementation(() => ({
            getSession,
            getUserId,
            getAttributes,
            incrementSessionEventCount
        }));

        const EVENT1_SCHEMA = 'com.amazon.rum.event1';
        const eventCache: EventCache = Utils.createDefaultEventCache();

        // Run
        eventCache.getEventBatch();
        eventCache.recordEvent(EVENT1_SCHEMA, {});

        // Assert
        expect(eventCache.hasEvents()).toBeTruthy();
    }


() => ({
            sessionId: 'a',
            record: true,
            eventCount: 1
        })


() => ({
            getSession,
            getUserId,
            getAttributes,
            incrementSessionEventCount
        })


async () => {
        // Init
        let eventCount = 0;
        const getSession = jest.fn().mockImplementation(() => {
            eventCount++;
            return {
                sessionId: 'a',
                record: true,
                eventCount: eventCount
            };
        });
        const getUserId = jest.fn(() => 'b');
        const getAttributes = jest.fn(() => {});
        const incrementSessionEventCount = jest.fn();
        (SessionManager as any).mockImplementation(() => ({
            getSession,
            getUserId,
            getAttributes,
            incrementSessionEventCount
        }));
        const EVENT1_SCHEMA = 'com.amazon.rum.event1';
        const config = {
            ...DEFAULT_CONFIG,
            ...{
                sessionEventLimit: 1
            }
        };
        const eventCache: EventCache = Utils.createEventCache(config);

        // Run
        eventCache.recordEvent(EVENT1_SCHEMA, {});
        eventCache.recordEvent(EVENT1_SCHEMA, {});
        eventCache.recordEvent(EVENT1_SCHEMA, {});

        // Assert
        expect(eventCache.getEventBatch().length).toEqual(1);
    }


() => {
            eventCount++;
            return {
                sessionId: 'a',
                record: true,
                eventCount: eventCount
            };
        }


async () => {
        // Init
        let eventCount = 0;
        const getSession = jest.fn(() => ({ sessionId: 'a', record: true }));
        const getUserId = jest.fn(() => 'b');
        const getAttributes = jest.fn(() => {});
        const incrementSessionEventCount = jest.fn();
        (SessionManager as any).mockImplementation(() => ({
            getSession,
            getUserId,
            getAttributes,
            incrementSessionEventCount
        }));
        const EVENT1_SCHEMA = 'com.amazon.rum.event1';
        const config = {
            ...DEFAULT_CONFIG,
            ...{
                sessionEventLimit: 0
            }
        };
        const eventCache: EventCache = Utils.createEventCache(config);

        // Run
        eventCache.recordEvent(EVENT1_SCHEMA, {});

        // Assert
        expect(eventCache.getEventBatch().length).toEqual(1);
    }


state => {
  return {
    search: state.customers.search,
    selectedCount: state.customers.selected.length,
  }
}


dispatch => {
  return {
    setSearch: value => {
      dispatch(setFilterSearch(value))
      dispatch(fetchCustomers())
    },
    onDelete: () => {
      dispatch(deleteCustomers())
    },
    onSetGroup: group_id => {
      dispatch(setGroup(group_id))
    },
  }
}


value => {
      dispatch(setFilterSearch(value))
      dispatch(fetchCustomers())
    }


() => {
      dispatch(deleteCustomers())
    }


group_id => {
      dispatch(setGroup(group_id))
    }


export function Home() {
  const [isOpen, setIsOpen] = useState(false);

  function handleClose() {
    setIsOpen(!isOpen);
  }

  return (
    <>
      <Sidebar isOpen={isOpen} toggle={handleClose} />
      <Navbar toggle={handleClose} />
    </>
  )
}


function handleClose() {
    setIsOpen(!isOpen);
  }


class ListTagController {
  async list(request: Request, response: Response) {
    const listTagService = new ListTagService();

    const tags = await listTagService.execute();

    return response.json(tags);
  }
}


async list(request: Request, response: Response) {
    const listTagService = new ListTagService();

    const tags = await listTagService.execute();

    return response.json(tags);
  }


() => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
          HomeComponent
      ],
      imports: [
          RouterTestingModule,
      ],
    }).compileComponents();
  }));
  it('should create the component', async(() => {
    const fixture = TestBed.createComponent(HomeComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app).toBeTruthy();
  }));
}


() => {
    TestBed.configureTestingModule({
      declarations: [
          HomeComponent
      ],
      imports: [
          RouterTestingModule,
      ],
    }).compileComponents();
  }


() => {
    const fixture = TestBed.createComponent(HomeComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app).toBeTruthy();
  }


(projet) => {
                                return <ion-col class={ 'column-' + this.cardsPerRow }>
                                    <img
                                        class='project-logo'
                                        src={this.rootPath + projet.directoryName + '/logo' + this.fileExtension}
                                        onClick={ () => this.goToProjectDetails(projet) }


@Component({
    tag: 'app-projects-gallery',
    styleUrl: 'app-projects-gallery.scss'
})
export class AppProjectsGallery {

    @State()
    private cardsPerRow: number;
    @State()
    private columns: number;

    @State()
    private projets: Projet[];
    @State()
    private fileExtension: string;
    @State()
    private rootPath: string;

    componentWillLoad() {
        this.computeGridProperties();
        this.projets = getProjets();
        this.fileExtension = getFilesExtension();
        this.rootPath = getProjectsRootPath();

    }

    /**
     * Ecoute les modification de taille de fenêtre
     */
    @Listen('window:resize')
    windowResize() {
        this.computeGridProperties();
    }

    /**
     * Calcule le nombre de colonnes de la galerie
     */
    private computeGridProperties() {
        if (this.columns) {
            this.cardsPerRow = +this.columns;
        } else {
            let width = window.innerWidth
            if (width <= 400) {
                this.cardsPerRow = 3;
            } else {
                this.cardsPerRow = 4;
            }
        }
    }

    private goToProjectDetails(projet: Projet)  {
        console.log(projet);
    }

    render() {

        return (
            <ion-page>
                <ion-content>
                    <ion-grid>
                        <ion-row>
                            { this.projets.map((projet) => {
                                return <ion-col class={ 'column-' + this.cardsPerRow }>
                                    <img
                                        class='project-logo'
                                        src={this.rootPath + projet.directoryName + '/logo' + this.fileExtension}
                                        onClick={ () => this.goToProjectDetails(projet) }/>
                                </ion-col>
                            }) }


componentWillLoad() {
        this.computeGridProperties();
        this.projets = getProjets();
        this.fileExtension = getFilesExtension();
        this.rootPath = getProjectsRootPath();

    }


/**
     * Ecoute les modification de taille de fenêtre
     */
@Listen('window:resize')
    windowResize() {
        this.computeGridProperties();
    }


/**
     * Calcule le nombre de colonnes de la galerie
     */
private computeGridProperties() {
        if (this.columns) {
            this.cardsPerRow = +this.columns;
        } else {
            let width = window.innerWidth
            if (width <= 400) {
                this.cardsPerRow = 3;
            } else {
                this.cardsPerRow = 4;
            }
        }
    }


private goToProjectDetails(projet: Projet)  {
        console.log(projet);
    }


render() {

        return (
            <ion-page>
                <ion-content>
                    <ion-grid>
                        <ion-row>
                            { this.projets.map((projet) => {
                                return <ion-col class={ 'column-' + this.cardsPerRow }>
                                    <img
                                        class='project-logo'
                                        src={this.rootPath + projet.directoryName + '/logo' + this.fileExtension}
                                        onClick={ () => this.goToProjectDetails(projet) }/>
                                </ion-col>
                            }) }


/** Base class for the instances of 'Component' that represent data, i.e. value. */
export abstract class DataHolder extends Component {

    protected data: any = undefined; // actual value
    private readonly schema: IDataSchema = undefined; // schema

    public constructor(name: string, parent: ComponentOwner, schema: IDataSchema){
        super(name, parent);

        this.schema = schema;

        this.getModel().getValidator().addSchema(this.schema, this.getFullPath());

        this.reset();
    }

    //#region Reset/initialize value

    /** Resets data to its default value according to the schema. */
    public reset(){
        if(DataHolder.hasConst(this.schema)){
            this.data = this.schema.const;
        }else if(DataHolder.hasFakeTrue(this.schema)){
            this.fakeData();
        }else if(this.hasType()){
            this.data = jsonInstantiator.instantiate(this.schema);
        }else if(this.hasDefault()){
            this.data = this.schema.default;
        }else{
            this.data = undefined;
        }
    }

    protected isFake(){
        return !DataHolder.hasConst(this.schema) && DataHolder.hasFakeTrue(this.schema);
    }

    protected hasDefault(){
        return this.schema.default !== undefined;
    }

    protected hasType(){
        return this.schema.type !== undefined;
    }

    public static hasFakeTrue(schema: IDataSchema){
        return schema.fake === true;
    }

    public static hasConst(schema: IDataSchema){
        return schema.const !== undefined;
    }

    public static isReadOnly(schema: IDataSchema){
        return DataHolder.hasConst(schema) || DataHolder.hasFakeTrue(schema);
    }

    //#endregion

    /** Fakes data using the schema */
    protected fakeData(){
        this.data = jsf(this.schema);
    }

    /**
     * Validates the given value against the schema.
     *
     * Returns true - if the value is valid, false - otherwise.
     *
     * @param value Value to validate.
     * @param withError If true, then in case of validation failure an error
     * will be thrown.
     * @param opDescr A string descibing in which context validation is performed, e.g.
     * which operation required validation. Will be used in the message of the error
     * in case the latter is thrown.
     */
    protected validate(value: any, withError: boolean = false, opDescr: string = undefined): boolean {
        if(this.getModel().getValidator().validate(this.getFullPath(), value)){
            return true;
        }else if(withError){
            u.fatal("Validation failed: " + (opDescr ? "\n" + opDescr : "")
                + "\nReason: " + this.getModel().getValidator().errorsText(),
                this.getFullPath());
        }
        return false;
    }

    /**
     * Composes and returns a string describing an operation
     * that is being performed over data.
     *
     * @param operation A valid read or write operation.
     * @param path The relative path of the affected entry in data.
     * @param value The value that is being written in case of a write operation.
     */
    protected getOperationString(operation: ReadOp|WriteOp, path: string, value: any = undefined){
        return "Operation: " + operation
                + (value !== undefined ? "\nValue: " + JSON.stringify(value, null, 4) : "")
                + "\nPath: " + (path === '' ? "root" : path);
    }

    /**
     * Checks whether data has an entry with the given path.
     *
     * Returns true - if check succeeds (i.e. an entry is present),
     * false - otherwise.
     *
     * @param path The relative path of the entry in data.
     * @param expectedType The expected type of the entry. If this parameter
     * is provided and the entry is of a different type, the check will fail.
     * @param withError If true, then in case of check failure an error
     * will be thrown.
     * @param opDescr A string descibing in which context the check is performed, e.g.
     * which operation required this check. Will be used in the message of the error
     * in case the latter is thrown.
     */
    public hasEntry(path: string, expectedType: any = undefined, withError: boolean = false, opDescr: string = undefined): boolean {

        if(!jsonPointer.has(this.data, path)){

            if(withError){
                u.fatal("No such entry."
                        + (opDescr ? "\n" + opDescr : "")
                        + "\nData: \n"
                        + JSON.stringify(this.data, null, 4),
                        this.getFullPath());
            }
            return false;

        }else if(expectedType !== undefined){

            let value = jsonPointer.get(this.data, path);

            if(!u.instanceOf(value, expectedType)){
                if(withError){
                    u.fatal("Incorrect type."
                        + (opDescr ? "\n" + opDescr : "")
                        + "\nExpected type: "
                        + u.getTypeNameFromType(expectedType)
                        + "\nActual type: "
                        + u.getTypeNameFromValue(value),
                        this.getFullPath());
                }
                return false;
            }
        }
        return true;
    }

    /**
     * Creates and returns an instance of:
     * - 'ReadOnlyData' in case the given schema contains 'const' or 'fake'
     * - 'Data' - otherwise
     *
     * @param name A name for the instance (name of the node).
     * @param parent A parent for the instance (parent node)
     * @param schema A valid schema object.
     */
    public static getInstance(name: string, parent: ComponentOwner, schema: IDataSchema): DataHolder {
        if(this.isReadOnly(schema)){
            return new ReadOnlyData(name, parent, schema);
        }else{
            return new Data(name, parent, schema);
        }
    }
}


/** Base class for the instances of 'DataHolder' that can be read. */
export abstract class ReadableData extends DataHolder {

    /**
     * Performs the given read operation from the given path in data
     * and returns the result if successful, throws an error otherwise.
     *
     * An error may be thrown in the following cases:
     * - an entry under the given path does not exist
     * - the given operation will lead to incompliance with the schema
     * - the given operation is not allowed on the addressed entry in data
     * - the given operation is invalid
     * - other internal errors happen
     *
     * @param operation A valid read operation. Allowed read operations
     * depend on the type of the entry addressed by the parameter 'path'.
     * @param path A path to an existing entry in data.
     */
    public read(operation: ReadOp, path: string = ""){

        /**
         * In case a read operation may lead to changes in data (e.g. 'pop'),
         * the operation will be first performed on a copy of data, then the
         * copy will be validated. If the copy passes validation, then the
         * operation will be performed on the original data,
         * otherwise an error will be thrown.
         */

        // Fake instances generate new fake value on each read.
        if(this.isFake()){
            this.reset();
        }

        let opStr = this.getOperationString(operation, path);

        switch(operation){

            // return reference if object, value if primitive
            case ReadOp.get:
                // Check if the entry exists
                if(this.hasEntry(path, undefined, true, opStr)){
                    return jsonPointer.get(this.data, path);
                }

            // return a deep copy
            case ReadOp.copy:
                // Check if the entry exists
                if(this.hasEntry(path, undefined, true, opStr)){
                    return u.copy(jsonPointer.get(this.data, path));
                }

            // pop from array and return
            case ReadOp.pop:
                // the 'pop' operation on a readonly data is not allowed
                if(this instanceof ReadOnlyData){
                    u.fatal("Invalid operation on a constant:\n" + opStr, this.getFullPath());
                }
                // Check if the entry exists and it is an array
                if(this.hasEntry(path, Array, true, opStr)){
                    let copy = u.copy(this.data);
                    jsonPointer.get(copy, path).pop();
                    // validate the copy with an error if invaild
                    if(this.validate(copy, true, opStr)){
                        // modify original data after successful validation
                        return jsonPointer.get(this.data, path).pop();
                    }
                }

            // return length of an array or string
            case ReadOp.length:
                // Check if the entry exists and it is an array or a string
                if(this.hasEntry(path, Array, false, opStr)
                    || this.hasEntry(path, String, true, opStr)){
                    return jsonPointer.get(this.data, path).length;
                }

            // return value parsed from a string
            case ReadOp.parse:
                // Check if the entry exists and it is a string
                if(this.hasEntry(path, String, true, opStr)){
                    return JSON.parse(jsonPointer.get(this.data, path));
                }
        }
        u.fatal("Invalid operation:\n" + opStr, this.getFullPath());
    }
}