() => {
    let historyController: HistoryController;
    let env: Mock.IMockEnvironment;

    beforeEach(() => {
      env = new Mock.MockEnvironmentBuilder().withLiveQueryStateModel().build();
      historyController = new HistoryController(env.root, Mock.mockWindow(), env.queryStateModel, env.queryController, env.usageAnalytics);
    });

    afterEach(() => {
      historyController = null;
      env = null;
    });

    it('should set the query state model representation on all event in the hash', () => {
      env.queryStateModel.attributes = {
        a: 'a',
        b: 'b',
        c: 'notDefault',
        d: [1, 2, 3]
      };

      env.queryStateModel.defaultAttributes = {
        a: 'a',
        b: 'b',
        c: 'c',
        d: [2, 3, 4]
      };

      $$(historyController.element).trigger('state:all');
      Defer.flush();
      expect(historyController.window.location.hash).toBe('#c=notDefault&d=[1,2,3]');
    });

    it('should listen to hashchange event', () => {
      expect(historyController.window.addEventListener).toHaveBeenCalledWith('hashchange', jasmine.any(Function));
    });

    it('should not throw when history controller does not have an analytics client and there is a hash change', () => {
      historyController = new HistoryController(env.root, Mock.mockWindow(), env.queryStateModel, env.queryController);
      historyController.setHashValues({ q: 'test' });
      expect(historyController.handleHashChange.bind(historyController)).not.toThrow();
    });

    it('should not set the hash when it has not changed on the first hash change', () => {
      $$(historyController.element).trigger(InitializationEvents.restoreHistoryState);
      expect(historyController.window.location.replace).not.toHaveBeenCalled();
    });

    it('should not update the model hen simply replacing the state from an old value', () => {
      historyController = new HistoryController(env.root, Mock.mockWindow(), env.queryStateModel, env.queryController);
      spyOn(env.queryStateModel, 'setMultiple');
      historyController.replaceState({ q: 'bar' });
      expect(env.queryStateModel.setMultiple).not.toHaveBeenCalled();
    });

    describe('with a fake HashUtilsModule', () => {
      let fakeHashUtils;
      beforeEach(() => {
        fakeHashUtils = {} as any;
        fakeHashUtils.getValue = jasmine.createSpy('getValue');
        fakeHashUtils.getHash = jasmine.createSpy('getHash').and.callFake(() => Mock.mockWindow().location.hash);
        fakeHashUtils.encodeValues = jasmine.createSpy('encodeValues');
        historyController.hashUtils = fakeHashUtils;
      });

      it('keeps parsing hash values after one fails to parse', () => {
        let threwError = false;
        env.queryStateModel.attributes = {
          a: 1,
          b: 2,
          c: 3
        };

        const throwsAnError = () => {
          if (!threwError) {
            threwError = true;
            throw new Error();
          }
        };

        historyController.hashUtils.getValue = jasmine.createSpy('getValue').and.callFake(throwsAnError);

        $$(env.root).trigger(InitializationEvents.restoreHistoryState);

        expect(historyController.hashUtils.getValue).toHaveBeenCalledTimes(_.size(env.queryStateModel.attributes));
      });

      describe('when logging analytics event', () => {
        beforeEach(() => {
          historyController = new HistoryController(env.root, window, env.queryStateModel, env.queryController, env.usageAnalytics);
          historyController.hashUtils = fakeHashUtils;
          $$(historyController.element).trigger(InitializationEvents.restoreHistoryState);
        });

        afterEach(() => {
          window.location.hash = '';
        });

        const simulateHashModule = (key, value) => {
          historyController.hashUtils.getValue = jasmine.createSpy('getValue').and.callFake((valueNeeded: string) => {
            if (valueNeeded == key) {
              return value;
            }
            return undefined;
          });
        };

        const assertFacetAnalyticsCall = (cause: IAnalyticsActionCause) => {
          expect(historyController.usageAnalytics.logSearchEvent).toHaveBeenCalledWith(cause, {
            facetId: '@foo',
            facetField: '@foo',
            facetTitle: '@foo',
            facetValue: 'bar'
          } as IAnalyticsFacetMeta);
        };

        it('should log an analytics event when q changes', () => {
          simulateHashModule('q', 'foo');
          window.dispatchEvent(new Event('hashchange'));
          expect(historyController.usageAnalytics.logSearchEvent).toHaveBeenCalledWith(analyticsActionCauseList.searchboxSubmit, {});
        });

        it('should log an analytics event when sort changes', () => {
          simulateHashModule('sort', 'date ascending');
          window.dispatchEvent(new Event('hashchange'));
          expect(historyController.usageAnalytics.logSearchEvent).toHaveBeenCalledWith(analyticsActionCauseList.resultsSort, {
            resultsSortBy: 'date ascending'
          } as IAnalyticsResultsSortMeta);
        });

        it('should log an analytics event when a facet changes to select a value', () => {
          historyController.queryStateModel.registerNewAttribute('f:@foo', []);
          simulateHashModule('f:@foo', ['bar']);
          window.dispatchEvent(new Event('hashchange'));
          assertFacetAnalyticsCall(analyticsActionCauseList.facetSelect);
        });

        it('should log an analytics event when a facet changes to deselect a value', () => {
          historyController.queryStateModel.registerNewAttribute('f:@foo', []);
          simulateHashModule('f:@foo', ['bar']);
          window.dispatchEvent(new Event('hashchange'));
          simulateHashModule('f:@foo', []);
          window.dispatchEvent(new Event('hashchange'));
          assertFacetAnalyticsCall(analyticsActionCauseList.facetDeselect);
        });

        it('should log an analytics event when a facet changes to exclude a value', () => {
          historyController.queryStateModel.registerNewAttribute('f:@foo:not', []);
          simulateHashModule('f:@foo:not', ['bar']);
          window.dispatchEvent(new Event('hashchange'));
          assertFacetAnalyticsCall(analyticsActionCauseList.facetExclude);
        });

        it('should log an analytics event when a facet changes to unexclude a value', () => {
          historyController.queryStateModel.registerNewAttribute('f:@foo:not', []);
          simulateHashModule('f:@foo:not', ['bar']);
          window.dispatchEvent(new Event('hashchange'));
          simulateHashModule('f:@foo:not', []);
          window.dispatchEvent(new Event('hashchange'));
          assertFacetAnalyticsCall(analyticsActionCauseList.facetUnexclude);
        });
      });
    });
  }


() => {
      env = new Mock.MockEnvironmentBuilder().withLiveQueryStateModel().build();
      historyController = new HistoryController(env.root, Mock.mockWindow(), env.queryStateModel, env.queryController, env.usageAnalytics);
    }


() => {
      historyController = null;
      env = null;
    }


() => {
      env.queryStateModel.attributes = {
        a: 'a',
        b: 'b',
        c: 'notDefault',
        d: [1, 2, 3]
      };

      env.queryStateModel.defaultAttributes = {
        a: 'a',
        b: 'b',
        c: 'c',
        d: [2, 3, 4]
      };

      $$(historyController.element).trigger('state:all');
      Defer.flush();
      expect(historyController.window.location.hash).toBe('#c=notDefault&d=[1,2,3]');
    }


() => {
      expect(historyController.window.addEventListener).toHaveBeenCalledWith('hashchange', jasmine.any(Function));
    }


() => {
      historyController = new HistoryController(env.root, Mock.mockWindow(), env.queryStateModel, env.queryController);
      historyController.setHashValues({ q: 'test' });
      expect(historyController.handleHashChange.bind(historyController)).not.toThrow();
    }


() => {
      $$(historyController.element).trigger(InitializationEvents.restoreHistoryState);
      expect(historyController.window.location.replace).not.toHaveBeenCalled();
    }


() => {
      historyController = new HistoryController(env.root, Mock.mockWindow(), env.queryStateModel, env.queryController);
      spyOn(env.queryStateModel, 'setMultiple');
      historyController.replaceState({ q: 'bar' });
      expect(env.queryStateModel.setMultiple).not.toHaveBeenCalled();
    }


() => {
      let fakeHashUtils;
      beforeEach(() => {
        fakeHashUtils = {} as any;
        fakeHashUtils.getValue = jasmine.createSpy('getValue');
        fakeHashUtils.getHash = jasmine.createSpy('getHash').and.callFake(() => Mock.mockWindow().location.hash);
        fakeHashUtils.encodeValues = jasmine.createSpy('encodeValues');
        historyController.hashUtils = fakeHashUtils;
      });

      it('keeps parsing hash values after one fails to parse', () => {
        let threwError = false;
        env.queryStateModel.attributes = {
          a: 1,
          b: 2,
          c: 3
        };

        const throwsAnError = () => {
          if (!threwError) {
            threwError = true;
            throw new Error();
          }
        };

        historyController.hashUtils.getValue = jasmine.createSpy('getValue').and.callFake(throwsAnError);

        $$(env.root).trigger(InitializationEvents.restoreHistoryState);

        expect(historyController.hashUtils.getValue).toHaveBeenCalledTimes(_.size(env.queryStateModel.attributes));
      });

      describe('when logging analytics event', () => {
        beforeEach(() => {
          historyController = new HistoryController(env.root, window, env.queryStateModel, env.queryController, env.usageAnalytics);
          historyController.hashUtils = fakeHashUtils;
          $$(historyController.element).trigger(InitializationEvents.restoreHistoryState);
        });

        afterEach(() => {
          window.location.hash = '';
        });

        const simulateHashModule = (key, value) => {
          historyController.hashUtils.getValue = jasmine.createSpy('getValue').and.callFake((valueNeeded: string) => {
            if (valueNeeded == key) {
              return value;
            }
            return undefined;
          });
        };

        const assertFacetAnalyticsCall = (cause: IAnalyticsActionCause) => {
          expect(historyController.usageAnalytics.logSearchEvent).toHaveBeenCalledWith(cause, {
            facetId: '@foo',
            facetField: '@foo',
            facetTitle: '@foo',
            facetValue: 'bar'
          } as IAnalyticsFacetMeta);
        };

        it('should log an analytics event when q changes', () => {
          simulateHashModule('q', 'foo');
          window.dispatchEvent(new Event('hashchange'));
          expect(historyController.usageAnalytics.logSearchEvent).toHaveBeenCalledWith(analyticsActionCauseList.searchboxSubmit, {});
        });

        it('should log an analytics event when sort changes', () => {
          simulateHashModule('sort', 'date ascending');
          window.dispatchEvent(new Event('hashchange'));
          expect(historyController.usageAnalytics.logSearchEvent).toHaveBeenCalledWith(analyticsActionCauseList.resultsSort, {
            resultsSortBy: 'date ascending'
          } as IAnalyticsResultsSortMeta);
        });

        it('should log an analytics event when a facet changes to select a value', () => {
          historyController.queryStateModel.registerNewAttribute('f:@foo', []);
          simulateHashModule('f:@foo', ['bar']);
          window.dispatchEvent(new Event('hashchange'));
          assertFacetAnalyticsCall(analyticsActionCauseList.facetSelect);
        });

        it('should log an analytics event when a facet changes to deselect a value', () => {
          historyController.queryStateModel.registerNewAttribute('f:@foo', []);
          simulateHashModule('f:@foo', ['bar']);
          window.dispatchEvent(new Event('hashchange'));
          simulateHashModule('f:@foo', []);
          window.dispatchEvent(new Event('hashchange'));
          assertFacetAnalyticsCall(analyticsActionCauseList.facetDeselect);
        });

        it('should log an analytics event when a facet changes to exclude a value', () => {
          historyController.queryStateModel.registerNewAttribute('f:@foo:not', []);
          simulateHashModule('f:@foo:not', ['bar']);
          window.dispatchEvent(new Event('hashchange'));
          assertFacetAnalyticsCall(analyticsActionCauseList.facetExclude);
        });

        it('should log an analytics event when a facet changes to unexclude a value', () => {
          historyController.queryStateModel.registerNewAttribute('f:@foo:not', []);
          simulateHashModule('f:@foo:not', ['bar']);
          window.dispatchEvent(new Event('hashchange'));
          simulateHashModule('f:@foo:not', []);
          window.dispatchEvent(new Event('hashchange'));
          assertFacetAnalyticsCall(analyticsActionCauseList.facetUnexclude);
        });
      });
    }


() => {
        fakeHashUtils = {} as any;
        fakeHashUtils.getValue = jasmine.createSpy('getValue');
        fakeHashUtils.getHash = jasmine.createSpy('getHash').and.callFake(() => Mock.mockWindow().location.hash);
        fakeHashUtils.encodeValues = jasmine.createSpy('encodeValues');
        historyController.hashUtils = fakeHashUtils;
      }


() => Mock.mockWindow().location.hash


() => {
        let threwError = false;
        env.queryStateModel.attributes = {
          a: 1,
          b: 2,
          c: 3
        };

        const throwsAnError = () => {
          if (!threwError) {
            threwError = true;
            throw new Error();
          }
        };

        historyController.hashUtils.getValue = jasmine.createSpy('getValue').and.callFake(throwsAnError);

        $$(env.root).trigger(InitializationEvents.restoreHistoryState);

        expect(historyController.hashUtils.getValue).toHaveBeenCalledTimes(_.size(env.queryStateModel.attributes));
      }


() => {
          if (!threwError) {
            threwError = true;
            throw new Error();
          }
        }


() => {
        beforeEach(() => {
          historyController = new HistoryController(env.root, window, env.queryStateModel, env.queryController, env.usageAnalytics);
          historyController.hashUtils = fakeHashUtils;
          $$(historyController.element).trigger(InitializationEvents.restoreHistoryState);
        });

        afterEach(() => {
          window.location.hash = '';
        });

        const simulateHashModule = (key, value) => {
          historyController.hashUtils.getValue = jasmine.createSpy('getValue').and.callFake((valueNeeded: string) => {
            if (valueNeeded == key) {
              return value;
            }
            return undefined;
          });
        };

        const assertFacetAnalyticsCall = (cause: IAnalyticsActionCause) => {
          expect(historyController.usageAnalytics.logSearchEvent).toHaveBeenCalledWith(cause, {
            facetId: '@foo',
            facetField: '@foo',
            facetTitle: '@foo',
            facetValue: 'bar'
          } as IAnalyticsFacetMeta);
        };

        it('should log an analytics event when q changes', () => {
          simulateHashModule('q', 'foo');
          window.dispatchEvent(new Event('hashchange'));
          expect(historyController.usageAnalytics.logSearchEvent).toHaveBeenCalledWith(analyticsActionCauseList.searchboxSubmit, {});
        });

        it('should log an analytics event when sort changes', () => {
          simulateHashModule('sort', 'date ascending');
          window.dispatchEvent(new Event('hashchange'));
          expect(historyController.usageAnalytics.logSearchEvent).toHaveBeenCalledWith(analyticsActionCauseList.resultsSort, {
            resultsSortBy: 'date ascending'
          } as IAnalyticsResultsSortMeta);
        });

        it('should log an analytics event when a facet changes to select a value', () => {
          historyController.queryStateModel.registerNewAttribute('f:@foo', []);
          simulateHashModule('f:@foo', ['bar']);
          window.dispatchEvent(new Event('hashchange'));
          assertFacetAnalyticsCall(analyticsActionCauseList.facetSelect);
        });

        it('should log an analytics event when a facet changes to deselect a value', () => {
          historyController.queryStateModel.registerNewAttribute('f:@foo', []);
          simulateHashModule('f:@foo', ['bar']);
          window.dispatchEvent(new Event('hashchange'));
          simulateHashModule('f:@foo', []);
          window.dispatchEvent(new Event('hashchange'));
          assertFacetAnalyticsCall(analyticsActionCauseList.facetDeselect);
        });

        it('should log an analytics event when a facet changes to exclude a value', () => {
          historyController.queryStateModel.registerNewAttribute('f:@foo:not', []);
          simulateHashModule('f:@foo:not', ['bar']);
          window.dispatchEvent(new Event('hashchange'));
          assertFacetAnalyticsCall(analyticsActionCauseList.facetExclude);
        });

        it('should log an analytics event when a facet changes to unexclude a value', () => {
          historyController.queryStateModel.registerNewAttribute('f:@foo:not', []);
          simulateHashModule('f:@foo:not', ['bar']);
          window.dispatchEvent(new Event('hashchange'));
          simulateHashModule('f:@foo:not', []);
          window.dispatchEvent(new Event('hashchange'));
          assertFacetAnalyticsCall(analyticsActionCauseList.facetUnexclude);
        });
      }


() => {
          historyController = new HistoryController(env.root, window, env.queryStateModel, env.queryController, env.usageAnalytics);
          historyController.hashUtils = fakeHashUtils;
          $$(historyController.element).trigger(InitializationEvents.restoreHistoryState);
        }


() => {
          window.location.hash = '';
        }


(key, value) => {
          historyController.hashUtils.getValue = jasmine.createSpy('getValue').and.callFake((valueNeeded: string) => {
            if (valueNeeded == key) {
              return value;
            }
            return undefined;
          });
        }


(valueNeeded: string) => {
            if (valueNeeded == key) {
              return value;
            }
            return undefined;
          }


(cause: IAnalyticsActionCause) => {
          expect(historyController.usageAnalytics.logSearchEvent).toHaveBeenCalledWith(cause, {
            facetId: '@foo',
            facetField: '@foo',
            facetTitle: '@foo',
            facetValue: 'bar'
          } as IAnalyticsFacetMeta);
        }


() => {
          simulateHashModule('q', 'foo');
          window.dispatchEvent(new Event('hashchange'));
          expect(historyController.usageAnalytics.logSearchEvent).toHaveBeenCalledWith(analyticsActionCauseList.searchboxSubmit, {});
        }


() => {
          simulateHashModule('sort', 'date ascending');
          window.dispatchEvent(new Event('hashchange'));
          expect(historyController.usageAnalytics.logSearchEvent).toHaveBeenCalledWith(analyticsActionCauseList.resultsSort, {
            resultsSortBy: 'date ascending'
          } as IAnalyticsResultsSortMeta);
        }


() => {
          historyController.queryStateModel.registerNewAttribute('f:@foo', []);
          simulateHashModule('f:@foo', ['bar']);
          window.dispatchEvent(new Event('hashchange'));
          assertFacetAnalyticsCall(analyticsActionCauseList.facetSelect);
        }


() => {
          historyController.queryStateModel.registerNewAttribute('f:@foo', []);
          simulateHashModule('f:@foo', ['bar']);
          window.dispatchEvent(new Event('hashchange'));
          simulateHashModule('f:@foo', []);
          window.dispatchEvent(new Event('hashchange'));
          assertFacetAnalyticsCall(analyticsActionCauseList.facetDeselect);
        }


() => {
          historyController.queryStateModel.registerNewAttribute('f:@foo:not', []);
          simulateHashModule('f:@foo:not', ['bar']);
          window.dispatchEvent(new Event('hashchange'));
          assertFacetAnalyticsCall(analyticsActionCauseList.facetExclude);
        }


() => {
          historyController.queryStateModel.registerNewAttribute('f:@foo:not', []);
          simulateHashModule('f:@foo:not', ['bar']);
          window.dispatchEvent(new Event('hashchange'));
          simulateHashModule('f:@foo:not', []);
          window.dispatchEvent(new Event('hashchange'));
          assertFacetAnalyticsCall(analyticsActionCauseList.facetUnexclude);
        }


() => {
        new RegisterView();
    }


class RegisterView extends  View {
    constructor() {
         super("Register", "btnRegister");

    }
    onButtonClick(): void {
        let registerModel: RegisterModel =
            new RegisterModel();
        if (registerModel.validate("registerForm", "btnRegister")){
            toastr.info(`${JSON.stringify(registerModel)}`);
            localStorage.setItem(registerModel.email, JSON.stringify(registerModel));
        }
        else{
            toastr.error("Please enter all required fields!");
        }
    }
}


onButtonClick(): void {
        let registerModel: RegisterModel =
            new RegisterModel();
        if (registerModel.validate("registerForm", "btnRegister")){
            toastr.info(`${JSON.stringify(registerModel)}`);
            localStorage.setItem(registerModel.email, JSON.stringify(registerModel));
        }
        else{
            toastr.error("Please enter all required fields!");
        }
    }


@Component({
  selector: 'kpn-leg-not-found-dialog',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <kpn-dialog>
      <div mat-dialog-title i18n="@@leg-not-found-dialog.title">No path</div>
      <div mat-dialog-content i18n="@@leg-not-found-dialog.message">
        The planner did not find a path to the selected destination.
      </div>
    </kpn-dialog>
  `,
})
export class LegNotFoundDialogComponent {}


@Injectable()
export class MockWorkbenchEditorService {
  open() {}
  apply() {}
}


open() {}


apply() {}


function HostMicrophoneButton(props: {
    service: JDService
    server?: AnalogSensorServer
    visible: boolean
}) {
    const { server, service, visible } = props

    const enabledRegister = useRegister(service, SoundLevelReg.Enabled)
    const minDecibelsRegister = useRegister(service, SoundLevelReg.MinDecibels)
    const maxDecibelsRegister = useRegister(service, SoundLevelReg.MaxDecibels)

    const enabled = useRegisterBoolValue(enabledRegister, props)
    const [minDecibels] = useRegisterUnpackedValue<[number]>(
        minDecibelsRegister,
        props
    )
    const [maxDecibels] = useRegisterUnpackedValue<[number]>(
        maxDecibelsRegister,
        props
    )
    const { volume, onClickActivateMicrophone } = useMicrophoneVolume(
        enabled && !!server,
        { fftSize: 64, smoothingTimeConstant: 0, minDecibels, maxDecibels }
    )
    const title = enabled ? "Stop microphone" : "Start microphone"

    const handleClick = async () => {
        if (!enabled && server) await onClickActivateMicrophone()
        await enabledRegister.sendSetBoolAsync(!enabled, true)
    }

    // update volume on demand
    useEffect(
        () =>
            visible &&
            server?.subscribe(REFRESH, () => {
                const v = volume?.()
                if (v !== undefined) {
                    server.reading.setValues([v])
                }
            }),
        [server, volume, visible]
    )

    return (
        <IconButtonWithProgress
            title={title}
            indeterminate={enabled}
            onClick={handleClick}
        >
            <MicIcon />
        </IconButtonWithProgress>
    )
}


export default function DashboardSoundLevel(props: DashboardServiceProps) {
    const { visible, service } = props
    const soundLevelRegister = useRegister(service, SoundLevelReg.SoundLevel)
    const [soundLevel] = useRegisterUnpackedValue<[number]>(
        soundLevelRegister,
        props
    )
    const server = useServiceServer<AnalogSensorServer>(service)

    if (soundLevel === undefined) return <LoadingProgress />

    return (
        <Grid container direction="column">
            <Grid item>
                <TrendWidget
                    register={soundLevelRegister}
                    min={0}
                    max={1}
                    horizon={64}
                />
            </Grid>
            <Grid item>
                <HostMicrophoneButton
                    service={service}
                    server={server}
                    visible={visible}
                />
            </Grid>
        </Grid>
    )
}


async () => {
        if (!enabled && server) await onClickActivateMicrophone()
        await enabledRegister.sendSetBoolAsync(!enabled, true)
    }


() =>
            visible &&
            server?.subscribe(REFRESH, () => {
                const v = volume?.()
                if (v !== undefined) {
                    server.reading.setValues([v])
                }
            })


() => {
                const v = volume?.()
                if (v !== undefined) {
                    server.reading.setValues([v])
                }
            }


async function check() {
    // @ts-ignore
    await action.execute({ embeddable: child });
  }


() => {
  const mock = jest.fn();
  mock.mockReturnValue({ close: jest.fn() });
  return mock;
}


async (done) => {
  const container = new TimeRangeContainer(
    {
      timeRange: { from: 'now-15m', to: 'now' },
      panels: {
        '1': {
          type: TIME_RANGE_EMBEDDABLE,
          explicitInput: {
            id: '1',
          },
        },
        '2': {
          type: TIME_RANGE_EMBEDDABLE,
          explicitInput: {
            id: '2',
          },
        },
      },
      id: '123',
    },
    (() => {}) as any
  );

  await container.untilEmbeddableLoaded('1');
  await container.untilEmbeddableLoaded('2');

  const child1 = container.getChild<TimeRangeEmbeddable>('1');
  expect(child1).toBeDefined();
  expect(child1.getInput().timeRange).toEqual({ from: 'now-15m', to: 'now' });

  const child2 = container.getChild<TimeRangeEmbeddable>('2');
  expect(child2).toBeDefined();
  expect(child2.getInput().timeRange).toEqual({ from: 'now-15m', to: 'now' });

  const openModalMock = createOpenModalMock();

  new CustomTimeRangeAction({
    openModal: openModalMock,
    commonlyUsedRanges: [],
    dateFormat: 'MM YYY',
  }).execute({
    embeddable: child1,
  });

  await nextTick();
  const openModal = openModalMock.mock.calls[0][0] as ReactElement;

  const wrapper = mount(openModal);
  wrapper.setState({ timeRange: { from: 'now-30days', to: 'now-29days' } });

  findTestSubject(wrapper, 'addPerPanelTimeRangeButton').simulate('click');

  const subscription = Rx.merge(container.getOutput$(), container.getInput$())
    .pipe(skip(2))
    .subscribe(() => {
      expect(child1.getInput().timeRange).toEqual({ from: 'now-30days', to: 'now-29days' });
      expect(child2.getInput().timeRange).toEqual({ from: 'now-30m', to: 'now-1m' });
      subscription.unsubscribe();
      done();
    });

  container.updateInput({ timeRange: { from: 'now-30m', to: 'now-1m' } });
}


() => {
      expect(child1.getInput().timeRange).toEqual({ from: 'now-30days', to: 'now-29days' });
      expect(child2.getInput().timeRange).toEqual({ from: 'now-30m', to: 'now-1m' });
      subscription.unsubscribe();
      done();
    }


async (done) => {
  const container = new TimeRangeContainer(
    {
      timeRange: { from: 'now-15m', to: 'now' },
      panels: {
        '1': {
          type: TIME_RANGE_EMBEDDABLE,
          explicitInput: {
            id: '1',
          },
        },
        '2': {
          type: TIME_RANGE_EMBEDDABLE,
          explicitInput: {
            id: '2',
          },
        },
      },
      id: '123',
    },
    (() => {}) as any
  );

  await container.untilEmbeddableLoaded('1');
  await container.untilEmbeddableLoaded('2');

  const child1 = container.getChild<TimeRangeEmbeddable>('1');
  const child2 = container.getChild<TimeRangeEmbeddable>('2');

  const openModalMock = createOpenModalMock();
  new CustomTimeRangeAction({
    openModal: openModalMock,
    commonlyUsedRanges: [],
    dateFormat: 'MM YYY',
  }).execute({
    embeddable: child1,
  });

  await nextTick();
  const openModal = openModalMock.mock.calls[0][0] as ReactElement;

  const wrapper = mount(openModal);
  wrapper.setState({ timeRange: { from: 'now-30days', to: 'now-29days' } });

  findTestSubject(wrapper, 'addPerPanelTimeRangeButton').simulate('click');

  container.updateInput({ timeRange: { from: 'now-30m', to: 'now-1m' } });

  new CustomTimeRangeAction({
    openModal: openModalMock,
    commonlyUsedRanges: [],
    dateFormat: 'MM YYY',
  }).execute({
    embeddable: child1,
  });

  await nextTick();
  const openModal2 = openModalMock.mock.calls[1][0];

  const wrapper2 = mount(openModal2);
  findTestSubject(wrapper2, 'removePerPanelTimeRangeButton').simulate('click');

  const subscription = Rx.merge(container.getOutput$(), container.getInput$())
    .pipe(skip(2))
    .subscribe(() => {
      expect(child1.getInput().timeRange).toEqual({ from: 'now-10m', to: 'now-5m' });
      expect(child2.getInput().timeRange).toEqual({ from: 'now-10m', to: 'now-5m' });
      subscription.unsubscribe();
      done();
    });

  container.updateInput({ timeRange: { from: 'now-10m', to: 'now-5m' } });
}


() => {
      expect(child1.getInput().timeRange).toEqual({ from: 'now-10m', to: 'now-5m' });
      expect(child2.getInput().timeRange).toEqual({ from: 'now-10m', to: 'now-5m' });
      subscription.unsubscribe();
      done();
    }


async (done) => {
  const container = new TimeRangeContainer(
    {
      timeRange: { from: 'now-15m', to: 'now' },
      panels: {
        '1': {
          type: TIME_RANGE_EMBEDDABLE,
          explicitInput: {
            id: '1',
            timeRange: { to: '2', from: '1' },
          },
        },
        '2': {
          type: TIME_RANGE_EMBEDDABLE,
          explicitInput: {
            id: '2',
          },
        },
      },
      id: '123',
    },
    (() => {}) as any
  );

  await container.untilEmbeddableLoaded('1');
  await container.untilEmbeddableLoaded('2');

  const child1 = container.getChild<TimeRangeEmbeddable>('1');
  const child2 = container.getChild<TimeRangeEmbeddable>('2');

  const openModalMock = createOpenModalMock();
  new CustomTimeRangeAction({
    openModal: openModalMock,
    commonlyUsedRanges: [],
    dateFormat: 'MM YYY',
  }).execute({
    embeddable: child1,
  });

  await nextTick();
  const openModal = openModalMock.mock.calls[0][0] as ReactElement;

  const wrapper = mount(openModal);
  wrapper.setState({ timeRange: { from: 'now-300m', to: 'now-400m' } });

  findTestSubject(wrapper, 'cancelPerPanelTimeRangeButton').simulate('click');

  const subscription = Rx.merge(container.getOutput$(), container.getInput$())
    .pipe(skip(2))
    .subscribe(() => {
      expect(child1.getInput().timeRange).toEqual({ from: '1', to: '2' });
      expect(child2.getInput().timeRange).toEqual({ from: 'now-30m', to: 'now-1m' });
      subscription.unsubscribe();
      done();
    });

  container.updateInput({ timeRange: { from: 'now-30m', to: 'now-1m' } });
}


() => {
      expect(child1.getInput().timeRange).toEqual({ from: '1', to: '2' });
      expect(child2.getInput().timeRange).toEqual({ from: 'now-30m', to: 'now-1m' });
      subscription.unsubscribe();
      done();
    }


async () => {
  const container = new TimeRangeContainer(
    {
      timeRange: { from: 'now-15m', to: 'now' },
      panels: {
        '1': {
          type: TIME_RANGE_EMBEDDABLE,
          explicitInput: {
            id: '1',
          },
        },
      },
      id: '123',
    },
    (() => {}) as any
  );

  await container.untilEmbeddableLoaded('1');

  const child = container.getChild<TimeRangeEmbeddable>('1');

  const openModalMock = createOpenModalMock();
  const compatible = await new CustomTimeRangeAction({
    openModal: openModalMock,
    commonlyUsedRanges: [],
    dateFormat: 'MM YYY',
  }).isCompatible({
    embeddable: child,
  });
  expect(compatible).toBe(true);
}


async () => {
  const container = new HelloWorldContainer(
    {
      panels: {
        '1': {
          type: HELLO_WORLD_EMBEDDABLE,
          explicitInput: {
            id: '1',
          },
        },
      },
      id: '123',
    },
    (() => null) as any
  );

  await container.untilEmbeddableLoaded('1');

  const child = container.getChild<HelloWorldEmbeddable>('1');

  const openModalMock = createOpenModalMock();
  const action = await new CustomTimeRangeAction({
    openModal: openModalMock,
    dateFormat: 'MM YYYY',
    commonlyUsedRanges: [],
  });

  async function check() {
    // @ts-ignore
    await action.execute({ embeddable: child });
  }
  await expect(check()).rejects.toThrow(Error);
}


export default class ForEditor extends React.Component<IP, any> { }


export interface IToolbar {
  h1?: boolean;
  h2?: boolean;
  h3?: boolean;
  h4?: boolean;
  h5?: boolean;
  h6?: boolean;
  bold?: boolean;
  italic?: boolean;
  underline?: boolean;
  strikethrough?: boolean;
  img?: boolean;
  link?: boolean;
  code?: boolean;
  preview?: boolean;
  expand?: boolean;
  undo?: boolean;
  redo?: boolean;
  save?: boolean;
  subfield?: boolean;
}


interface IP {
  value?: string;
  lineNum?: number;
  onChange?: (value: string) => void;
  onSave?: (value: string) => void;
  placeholder?: string;
  fontSize?: string;
  disabled?: boolean;
  style?: object;
  height?: string;
  preview?: boolean;
  expand?: boolean;
  subfield?: boolean;
  toolbar?: IToolbar;
  language?: string;
  addImg?: (file: File, index: number) => void;
}


//List all the functions
declare class AFLB {
    sfw: {
      baka():Promise<AFLB.AFLBRequestResults>;
      angry():Promise<AFLB.AFLBRequestResults>;
      bite():Promise<AFLB.AFLBRequestResults>;
      bloodsuck():Promise<AFLB.AFLBRequestResults>;
      blush():Promise<AFLB.AFLBRequestResults>;
      bored():Promise<AFLB.AFLBRequestResults>;
      cheek():Promise<AFLB.AFLBRequestResults>;
      clap():Promise<AFLB.AFLBRequestResults>;
      cringe():Promise<AFLB.AFLBRequestResults>;
      revert():Promise<AFLB.AFLBRequestResults>;
      cry():Promise<AFLB.AFLBRequestResults>;
      dance():Promise<AFLB.AFLBRequestResults>;
      drink():Promise<AFLB.AFLBRequestResults>;
      facedesk():Promise<AFLB.AFLBRequestResults>;
      fight():Promise<AFLB.AFLBRequestResults>;
      hand():Promise<AFLB.AFLBRequestResults>;
      happy():Promise<AFLB.AFLBRequestResults>;
      hate():Promise<AFLB.AFLBRequestResults>;
      highfive():Promise<AFLB.AFLBRequestResults>;
      horny():Promise<AFLB.AFLBRequestResults>;
      kill():Promise<AFLB.AFLBRequestResults>;
      laugh():Promise<AFLB.AFLBRequestResults>;
      lick():Promise<AFLB.AFLBRequestResults>;
      lurk():Promise<AFLB.AFLBRequestResults>;
      meow():Promise<AFLB.AFLBRequestResults>;
      nom():Promise<AFLB.AFLBRequestResults>;
      nuzzle():Promise<AFLB.AFLBRequestResults>;
      panic():Promise<AFLB.AFLBRequestResults>;
      nya():Promise<AFLB.AFLBRequestResults>;
      pout():Promise<AFLB.AFLBRequestResults>;
      run():Promise<AFLB.AFLBRequestResults>;
      sad():Promise<AFLB.AFLBRequestResults>;
      sake():Promise<AFLB.AFLBRequestResults>;
      shoot():Promise<AFLB.AFLBRequestResults>;
      raise():Promise<AFLB.AFLBRequestResults>;
      sip():Promise<AFLB.AFLBRequestResults>;
      sipTea():Promise<AFLB.AFLBRequestResults>;
      sipCoffee():Promise<AFLB.AFLBRequestResults>;
      sipJuice():Promise<AFLB.AFLBRequestResults>;
      sipCacao():Promise<AFLB.AFLBRequestResults>;
      kissCheek():Promise<AFLB.AFLBRequestResults>;
      slap():Promise<AFLB.AFLBRequestResults>;
      slapAss():Promise<AFLB.AFLBRequestResults>;
      slapCheek():Promise<AFLB.AFLBRequestResults>;
      sleep():Promise<AFLB.AFLBRequestResults>;
      sleepSolo():Promise<AFLB.AFLBRequestResults>;
      sleepTogether():Promise<AFLB.AFLBRequestResults>;
      smile():Promise<AFLB.AFLBRequestResults>;
      smoke():Promise<AFLB.AFLBRequestResults>;
      steal():Promise<AFLB.AFLBRequestResults>;
      stokings():Promise<AFLB.AFLBRequestResults>;
      sweeties():Promise<AFLB.AFLBRequestResults>;
      sing():Promise<AFLB.AFLBRequestResults>;
      grin():Promise<AFLB.AFLBRequestResults>;
      choke():Promise<AFLB.AFLBRequestResults>;
      shrug():Promise<AFLB.AFLBRequestResults>;
      scare():Promise<AFLB.AFLBRequestResults>;
      scared():Promise<AFLB.AFLBRequestResults>;
      drawing():Promise<AFLB.AFLBRequestResults>;
      music():Promise<AFLB.AFLBRequestResults>;
      salute():Promise<AFLB.AFLBRequestResults>;
      tease():Promise<AFLB.AFLBRequestResults>;
      love():Promise<AFLB.AFLBRequestResults>;
      think():Promise<AFLB.AFLBRequestResults>;
      wasted():Promise<AFLB.AFLBRequestResults>;
      wave():Promise<AFLB.AFLBRequestResults>;
      wink():Promise<AFLB.AFLBRequestResults>;
      sex():Promise<AFLB.AFLBRequestResults>;
      cuddle():Promise<AFLB.AFLBRequestResults>;
      feed():Promise<AFLB.AFLBRequestResults>;
      hug():Promise<AFLB.AFLBRequestResults>;
      kiss():Promise<AFLB.AFLBRequestResults>;
      pat():Promise<AFLB.AFLBRequestResults>;
      poke():Promise<AFLB.AFLBRequestResults>;
      smug():Promise<AFLB.AFLBRequestResults>;
      stare():Promise<AFLB.AFLBRequestResults>;
      tickle():Promise<AFLB.AFLBRequestResults>;
      mix():Promise<AFLB.AFLBRequestResults>;
      neko():Promise<AFLB.AFLBRequestResults>;
      nekoImg():Promise<AFLB.AFLBRequestResults>;
      nekoGif():Promise<AFLB.AFLBRequestResults>;
      kitsune():Promise<AFLB.AFLBRequestResults>;
      forehead():Promise<AFLB.AFLBRequestResults>;
      watching():Promise<AFLB.AFLBRequestResults>;
      walking():Promise<AFLB.AFLBRequestResults>;
      plaid():Promise<AFLB.AFLBRequestResults>;
      cooking():Promise<AFLB.AFLBRequestResults>;
      shower():Promise<AFLB.AFLBRequestResults>;
      game():Promise<AFLB.AFLBRequestResults>;
      murr():Promise<AFLB.AFLBRequestResults>;
    }
    nsfw: {
      ass():Promise<AFLB.AFLBRequestResults>;
      ahegao():Promise<AFLB.AFLBRequestResults>;
      bdsm():Promise<AFLB.AFLBRequestResults>;
      blowjob():Promise<AFLB.AFLBRequestResults>;
      boobjob():Promise<AFLB.AFLBRequestResults>;
      cum():Promise<AFLB.AFLBRequestResults>;
      elves():Promise<AFLB.AFLBRequestResults>;
      hentai():Promise<AFLB.AFLBRequestResults>;
      hentai_gif():Promise<AFLB.AFLBRequestResults>;
      incest():Promise<AFLB.AFLBRequestResults>;
      masturbation():Promise<AFLB.AFLBRequestResults>;
      neko_nsfw():Promise<AFLB.AFLBRequestResults>;
      panties():Promise<AFLB.AFLBRequestResults>;
      tentacle():Promise<AFLB.AFLBRequestResults>;
      thighs():Promise<AFLB.AFLBRequestResults>;
    }
  }


export interface AFLBRequestResults {
      url: string;
    }


(e: FocusEvent) => {
  const target = e.currentTarget
  const input =
    target.querySelector('input') || target.querySelector('textarea')
  return input?.value !== undefined && input.value !== ''
}


(
  nextFocusTarget: Element | Node | null,
  inputArea: HTMLElement
) => {
  const portalRoot = getPortalRoot()
  if (!portalRoot.contains(nextFocusTarget)) {
    return false
  }
  if (portalRoot.contains(inputArea)) {
    return (
      ((nextFocusTarget as unknown) as Element)?.closest('portal-child') !==
      inputArea.closest('portal-child')
    )
  }
  return true
}


<
  Props extends {
    value?: any
    defaultValue?: any
  } = CompatibleHTMLProps<HTMLInputElement>
>({
  value,
  defaultValue,
}: Pick<Props, 'value' | 'defaultValue'>) => {
  if (value !== undefined) return value !== ''
  if (defaultValue !== undefined) return defaultValue !== ''
  return false
}


({
  checkValueOnBlur = defaultCheckValueOnBlur,
  hasValue: propsHasValue,
  labelOffset = '0rem',
}: UseFloatingLabelProps) => {
  const [isFocused, setIsFocused] = useState(false)
  const [hasValue, setHasValue] = useSyncedState(propsHasValue)

  const theme = useContext(ThemeContext)
  // Limitations of style/CSSProperties type
  // https://github.com/frenic/csstype#what-should-i-do-when-i-get-type-errors
  const style = {
    ['--label-translate' as any]: `${labelOffset}, ${theme.space.u4}`,
  }

  return {
    className: hasValue || isFocused ? 'label-up' : 'label-down',
    handlers: {
      onBlur: (e: FocusEvent<HTMLDivElement>) => {
        // Check for a value on blur – if there is one,
        // the label shouldn't move back down
        if (checkValueOnBlur) {
          setHasValue(checkValueOnBlur(e))
        }

        const nextFocusTarget = getNextFocusTarget(e)
        // For FieldSelect, focus can move (briefly) into the list,
        // which is in a Portal
        // (and a separate portal child from the input, if the input is also in aportal)
        const isInSelectList = getIsInSelectList(
          nextFocusTarget,
          e.currentTarget
        )
        if (
          nextFocusTarget &&
          !e.currentTarget.contains(nextFocusTarget) &&
          !isInSelectList
        ) {
          setIsFocused(false)
        }
      },
      onFocus: () => {
        setIsFocused(true)
      },
    },
    isFocused,
    style,
  }
}


(e: FocusEvent<HTMLDivElement>) => {
        // Check for a value on blur – if there is one,
        // the label shouldn't move back down
        if (checkValueOnBlur) {
          setHasValue(checkValueOnBlur(e))
        }

        const nextFocusTarget = getNextFocusTarget(e)
        // For FieldSelect, focus can move (briefly) into the list,
        // which is in a Portal
        // (and a separate portal child from the input, if the input is also in aportal)
        const isInSelectList = getIsInSelectList(
          nextFocusTarget,
          e.currentTarget
        )
        if (
          nextFocusTarget &&
          !e.currentTarget.contains(nextFocusTarget) &&
          !isInSelectList
        ) {
          setIsFocused(false)
        }
      }


() => {
        setIsFocused(true)
      }


(value: unknown) =>
    value === undefined ?
      ok(value) :
      fail(value, 'expected undefined')


(operation: Types.Operations, action: CryptoGen.Actions) => {
  if (operation) return false

  logger.error(
    `Crypto reducer: Action (${action.type}) did not contain operation ( "encrypt", "decrypt", "verify", "sign" )`
  )
  return true
}


(draftState, action) => {
    const {operation} = action.payload

    if (operationGuard(operation, action)) return

    const op = draftState[operation]
    op.bytesComplete = 0
    op.bytesTotal = 0
    op.inputType = 'text'
    op.input = new HiddenString('')
    op.output = new HiddenString('')
    op.outputStatus = undefined
    op.outputType = undefined
    op.outputSenderUsername = undefined
    op.outputSenderFullname = undefined
    op.errorMessage = new HiddenString('')
    op.warningMessage = new HiddenString('')
    op.outputValid = true
  }


(draftState, action) => {
    const {operation} = action.payload

    if (operationGuard(operation, action)) return

    if (operation === Constants.Operations.Encrypt) {
      const encrypt = draftState.encrypt
      encrypt.bytesComplete = 0
      encrypt.bytesTotal = 0
      encrypt.recipients = initialState.encrypt.recipients
      // Reset options since they depend on the recipients
      encrypt.options = initialState.encrypt.options
      encrypt.meta = initialState.encrypt.meta
      encrypt.output = new HiddenString('')
      encrypt.outputStatus = undefined
      encrypt.outputType = undefined
      encrypt.outputSenderUsername = undefined
      encrypt.outputSenderFullname = undefined
      encrypt.outputValid = false
      encrypt.errorMessage = new HiddenString('')
      encrypt.warningMessage = new HiddenString('')
    }
  }


(draftState, action) => {
    const {operation, recipients, hasSBS} = action.payload

    if (operationGuard(operation, action)) return

    if (operation !== Constants.Operations.Encrypt) return

    const op = draftState.encrypt

    // Output no longer valid since recipients have changed
    op.outputValid = false

    if (!op.recipients.length && recipients.length) {
      op.meta.hasRecipients = true
      op.meta.hasSBS = hasSBS
    }
    // Force signing when user is SBS
    if (hasSBS) {
      op.options.sign = true
    }

    if (recipients) {
      op.recipients = recipients
    }
  }


(draftState, action) => {
    const {options: newOptions, hideIncludeSelf} = action.payload
    const {encrypt} = draftState
    const oldOptions = encrypt.options
    encrypt.options = {
      ...oldOptions,
      ...newOptions,
    }

    // Output no longer valid since options have changed
    encrypt.outputValid = false

    // User set themselves as a recipient so don't show the 'includeSelf' option for encrypt (since they're encrypting to themselves)
    if (hideIncludeSelf) {
      encrypt.meta.hideIncludeSelf = hideIncludeSelf
      encrypt.options.includeSelf = false
    }
  }


(draftState, action) => {
    const {operation, type, value} = action.payload
    if (operationGuard(operation, action)) return

    const op = draftState[operation]
    const oldInput = op.input
    // Reset input to 'text' when no value given (cleared input or removed file upload)
    op.inputType = value.stringValue() ? type : 'text'
    op.input = value
    op.outputValid = oldInput.stringValue() === value.stringValue()
  }


(draftState, action) => {
    const {operation} = action.payload
    const op = draftState[operation]
    // For any file operation that completes, invalidate the output since multiple decrypt/verify operations will produce filenames with unqiue
    // counters on the end (as to not overwrite any existing files in the user's FS).
    // E.g. `${plaintextFilename} (n).ext`
    op.outputValid = false
    op.bytesComplete = 0
    op.bytesTotal = 0
  }


(draftState, action) => {
    const {
      input,
      operation,
      output,
      outputSigned,
      outputSenderFullname,
      outputSenderUsername,
      outputType,
      warning,
      warningMessage,
    } = action.payload
    if (operationGuard(operation, action)) return

    let inputAction:
      | CryptoGen.SaltpackDecryptPayload
      | CryptoGen.SaltpackEncryptPayload
      | CryptoGen.SaltpackSignPayload
      | CryptoGen.SaltpackVerifyPayload
      | undefined

    switch (input?.type) {
      // fallthrough
      case CryptoGen.saltpackDecrypt:
      case CryptoGen.saltpackEncrypt:
      case CryptoGen.saltpackSign:
      case CryptoGen.saltpackVerify:
        inputAction = input
        break
      default:
        inputAction = undefined
    }

    let outputValid = false

    const op = draftState[operation]

    if (inputAction) {
      outputValid = inputAction.payload.input.stringValue() === op.input.stringValue()

      // If the store's input matches its output, then we don't need to update with the value of the returning RPC.
      if (op.outputValid) {
        return
      }

      // Otherwise show the output but don't let them interact with it because the output is stale (newer RPC coming back)
      op.outputValid = outputValid
    }

    // Reset errors and warnings
    op.errorMessage = new HiddenString('')
    op.warningMessage = new HiddenString('')

    // Warning was set alongside successful output
    if (warning && warningMessage) {
      op.warningMessage = warningMessage
    }

    op.output = output
    op.outputStatus = 'success'
    op.outputType = outputType
    op.outputSigned = outputSigned
    op.outputSenderUsername = outputSenderUsername
    op.outputSenderFullname = outputSenderFullname
  }


(draftState, action) => {
    const {operation, errorMessage} = action.payload
    if (operationGuard(operation, action)) return

    const op = draftState[operation]
    // Clear output
    op.output = new HiddenString('')
    op.outputType = undefined

    // Set error
    op.outputStatus = 'error'
    op.errorMessage = errorMessage
  }


(draftState, action) => {
    const {bytesComplete, bytesTotal, operation} = action.payload
    if (operationGuard(operation, action)) return

    const op = draftState[operation]
    // The final progress notification might come after saltpackDone.
    // Reset progress when finsihed
    if (bytesComplete === bytesTotal) {
      op.bytesComplete = 0
      op.bytesTotal = 0
      return
    }
    op.bytesComplete = bytesComplete
    op.bytesTotal = bytesTotal
  }


(draftState: Container.Draft<Types.State>, action: TeamBuildingGen.Actions) => {
      const val = editTeambuildingDraft('crypto', draftState.teamBuilding, action)
      if (val !== undefined) {
        draftState.teamBuilding = val
      }
    }


type Actions = CryptoGen.Actions | TeamBuildingGen.Actions


@Component({
    selector: 'app-fullmap',
    templateUrl: './fullmap.component.html',
    styleUrls: ['./fullmap.component.scss']
})
export class FullmapComponent implements OnInit {

    myMarkers = [
        { id: 0, name: 'Canada', coords: { latitude: 56.130366, longitude: -106.346771 } },
        { id: 1, name: 'New York', coords: { latitude: 40.712784, longitude: -74.005941 } },
        { id: 2, name: 'Toronto', coords: { latitude: 43.653226, longitude: -79.383184 } },
        { id: 3, name: 'San Francisco', coords: { latitude: 37.774929, longitude: -122.419416 } },
        { id: 4, name: 'Utah', coords: { latitude: 39.320980, longitude: -111.093731 } }
    ];

    currLatitude = this.myMarkers[0].coords.latitude;
    currLongitude = this.myMarkers[0].coords.longitude;

    zoom: number = 4;
    scrollwheel = false;

    constructor(pt: PagetitleService) {
        pt.setTitle('Fullmap');
    }

    moveTo(coords) {
        this.currLatitude = coords.latitude;
        this.currLongitude = coords.longitude;
    }

    ngOnInit() {
    }

}


moveTo(coords) {
        this.currLatitude = coords.latitude;
        this.currLongitude = coords.longitude;
    }


ngOnInit() {
    }


/** Add an element **`A`** at the beginning of **`T`**
 * @param T to append to
 * @param A to be added to
 * @returns **`any[]`**
 * @example
 * ```ts
 * ```
 */
export type Prepend<T extends any[], A extends any> =
    ((head: A, ...args: T) => any) extends ((...args: infer U) => any)
    ? U
    : T


({
    children,
    id: idOverride,
    onBlur,
    onChange,
    onFocus,
    validate,
    parse,
    format,
    ...props
}) => {
    if (React.Children.count(children) !== 1) {
        throw new Error(
            '<ReferenceArrayInput> only accepts a single child (like <Datagrid>)'
        );
    }

    const { id, input, isRequired, meta } = useInput({
        id: idOverride,
        onBlur,
        onChange,
        onFocus,
        source: props.source,
        validate,
        parse,
        format,
        ...props,
    });

    const controllerProps = useReferenceArrayInputController({
        ...props,
        input,
    });

    const translate = useTranslate();

    return (
        <ReferenceArrayInputView
            id={id}
            input={input}
            isRequired={isRequired}
            meta={meta}
            translate={translate}
            children={children}
            {...props}
            {...controllerProps}
        />


searchText => (searchText ? { q: searchText } : {})


({
    crudGetMany,
    crudGetMatching,
    filterToQuery,
    perPage,
    referenceSource,
    ...rest
}: any) => sanitizeInputRestProps(rest)


({
    allowEmpty,
    basePath,
    children,
    choices,
    className,
    error,
    input,
    loading,
    isRequired,
    label,
    meta,
    onChange,
    options,
    resource,
    setFilter,
    setPagination,
    setSort,
    source,
    translate,
    warning,
    ...rest
}: ReferenceArrayInputViewProps) => {
    const translatedLabel = translate(
        label || `resources.${resource}.fields.${source}`,
        { _: label }
    );

    if (loading) {
        return (
            <Labeled
                label={translatedLabel}
                source={source}
                resource={resource}
                className={className}
                isRequired={isRequired}
            >
                <LinearProgress />
            </Labeled>


export interface ReferenceArrayInputProps extends InputProps {
    allowEmpty?: boolean;
    basePath?: string;
    children: ReactElement;
    classes?: any;
    className?: string;
    label?: string;
    reference: string;
    resource?: string;
    [key: string]: any;
}


export interface ReferenceArrayInputViewProps {
    allowEmpty?: boolean;
    basePath?: string;
    children: ReactElement;
    choices: any[];
    classes?: object;
    className?: string;
    error?: string;
    helperText?: string | boolean;
    id: string;
    input: FieldInputProps<any, HTMLElement>;
    isRequired: boolean;
    label?: string;
    loading: boolean;
    meta: FieldMetaState<any>;
    onChange: any;
    options?: any;
    reference: string;
    resource?: string;
    setFilter: (v: string) => void;
    setPagination: (pagination: PaginationPayload) => void;
    setSort: (sort: SortPayload, order?: string) => void;
    source: string;
    translate: Translate;
    warning?: string;
}


@Component({
  selector: 'hero-birthday',
  pipes: [MultiNumber],
  styles: [`
    h3{
        color:green;
    }
`],
  template: `
        The hero's birthday is :

{{ birthday }}

with pipe | date:

{{ birthday | date }}

with pipe - long date:

{{ birthday | date : 'longDate'}}

with pipe - short date:

{{ birthday | date : 'shortDate'}}

nullable:

birthday - nullable:

{{ myHero?.date | date : 'shortDate'}}

other way

{{ myHero && myHero.date | date : 'shortDate'}}

json: {{myHero | json}}

more samples

dd/MM/yy

{{ birthday | date : 'dd/MM/yy'}}

custom pipe - multi

multi 10

 {{10 | multiPipe }}

`
})
export class HeroBirthdayComponent {
  birthday = new Date(1988, 3, 15); // April 15, 1988

  myHero = {
    name: 'Bar',
    date: new Date(1988, 3, 15)
  }

  birthday22: any = null;//new Date(1988, 3, 15); // April 15, 1988
}


function resetRegexes() {
        ROUTER_REGEX.lastIndex = 0;
        ROUTES_NO_MIDDLEWARES_REGEX.lastIndex = 0;
        ROUTES_REGEX.lastIndex = 0;
        MIDDLEWARES_REGEX.lastIndex = 0;
        ROUTES_MIDDLEWARES_REGEX.lastIndex = 0;
        PATH_PARAM_REGEX_SLASH.lastIndex = 0;
        PATH_PARAM_REGEX_DOT.lastIndex = 0;
        PATH_PARAM_REGEX_END.lastIndex = 0;
        PATH_PARAM_TYPE_REGEX.lastIndex = 0;
        PATH_PARAM_STAR_REGEX.lastIndex = 0;
    }


function generateModelDefinitions() {
    const entityDirectory = path.join(__dirname, "../api/src/entity");
    const entityFiles = fs.readdirSync(entityDirectory);

    const enums: {
        [name: string]: string[];
    } = {};

    for (const entityFile of entityFiles) {
        let content = getContent(entityFile);
        const result = new RegExp(`export enum (.*?) {`).exec(content);
            if (result && result[1]) {
            const className = getClassName(result);
            const r = /(\w*?) ?= ?"(\w*?)"/g;
            let property;
            while (property = r.exec(content)) {
                if (property && property[2]) {
                    if (!enums[className]) {
                        enums[className] = [];
                    }
                    enums[className].push(property[2]);
                }
            }
        }
    }
    for (const entityFile of entityFiles) {
        const entityPath = path.join(entityDirectory, entityFile);
        let content = getContent(entityFile);
        const result = new RegExp(`export class (.*?) {`).exec(content);
        if (result && result[1]) {
            const className = getClassName(result);
                const properties: {
                [propertyName: string]: {
                    type: any;
                    required: boolean;
                };
            } = {};
            let property;
            const r = /public (.*?): (.*?);/g
            while (property = r.exec(content)) {
                if (property && property[1] && property[2]) {
                    properties[property[1].replace("?", "")] = {
                        type: property[2],
                        required: !property[1].endsWith("?"),
                    };
                }
            }
            swaggerDefinition.definitions[className] = {
                type: "object",
                required: Object.entries(properties).filter((p) => p[1].required).map((p) => p[0]),
                properties: {},
            };
            for (const p of Object.entries(properties)) {
                let type = p[1].type;
                if (enums[type]) {
                    swaggerDefinition.definitions[className].properties[p[0]] = {
                        type: "string",
                        enum: enums[type],
                    };
                } else if (type.startsWith("Record")) {
                    swaggerDefinition.definitions[className].properties[p[0]] = {
                        type: "object",
                    }
                } else if (type.endsWith("[]")) {
                    if (type.startsWith("any")) {
                        swaggerDefinition.definitions[className].properties[p[0]] = {
                            type: "array",
                            items: {
                                type: "object",
                            },
                        };
                    } else {
                        swaggerDefinition.definitions[className].properties[p[0]] = {
                            type: "array",
                            items: {
                                $ref: `#/definitions/${type.replace("[]", "")}`,
                            }
                        }
                    }
                } else if (type == "Date") {
                    swaggerDefinition.definitions[className].properties[p[0]] = {
                        type: "string",
                        format: "date"
                    };
                } else if (type.indexOf(" | ") !== -1) {
                    swaggerDefinition.definitions[className].properties[p[0]] = {
                        type: "string",
                        enum: type.replace(/ \| /g, ",").replace(/\"/g, "").split(","),
                    };
                } else if (type[0] == type[0].toUpperCase()) {
                    swaggerDefinition.definitions[className].properties[p[0]] = {
                        type: {
                            $ref: `#/definitions/${type}`,
                        },
                    };
                } else {
                    swaggerDefinition.definitions[className].properties[p[0]] = {
                        type,
                    };
                }
            }
        }
    }
    function getContent(entityFile: string) {
        const entityPath = path.join(entityDirectory, entityFile);
        let content = fs.readFileSync(entityPath).toString();
        return content;
    }

    function getClassName(result: RegExpExecArray) {
        return result[1].indexOf(" ") ? result[1].split(" ").shift() : result[1];
    }
}


function getContent(entityFile: string) {
        const entityPath = path.join(entityDirectory, entityFile);
        let content = fs.readFileSync(entityPath).toString();
        return content;
    }


function getClassName(result: RegExpExecArray) {
        return result[1].indexOf(" ") ? result[1].split(" ").shift() : result[1];
    }


(p) => ({
                    in: "path",
                    name: p,
                    type: "ToDo",
                    required: true,
                    description: "ToDo",
                })


(p) => p[1].required


(p) => p[0]


function _commonErrorHandler (err, reject) {
  if (err.message.indexOf('query returned empty result') > 0) {
    reject(new HttpError(err.message, 404))
  } else {
    reject(new Error(err.message))
  }
}


function _ssrHydrateSubcomponents (components, store, router, resolve, reject, app, context) {
  Promise.all(components.map(SubComponent => {
    if (SubComponent.asyncData) {
      return SubComponent.asyncData({
        store,
        route: router.currentRoute,
        context
      })
    } else {
      return Promise.resolve(null)
    }
  })).then(() => {
    if (buildTimeConfig.ssr.useInitialStateFilter) {
      context.state = omit(store.state, store.state.config.ssr.initialStateFilter)
    } else {
      context.state = store.state
    }
    if (!buildTimeConfig.server.dynamicConfigReload) { // if dynamic config reload then we're sending config along with the request
      context.state = omit(store.state, ['config'])
    } else {
      const excludeFromConfig = buildTimeConfig.server.dynamicConfigExclude
      const includeFromConfig = buildTimeConfig.server.dynamicConfigInclude
      console.log(excludeFromConfig, includeFromConfig)
      if (includeFromConfig && includeFromConfig.length > 0) {
        context.state.config = pick(context.state.config, includeFromConfig)
      }
      if (excludeFromConfig && excludeFromConfig.length > 0) {
        context.state.config = omit(context.state.config, excludeFromConfig)
      }
    }
    resolve(app)
  }).catch(err => {
    _commonErrorHandler(err, reject)
  })
}


SubComponent => {
    if (SubComponent.asyncData) {
      return SubComponent.asyncData({
        store,
        route: router.currentRoute,
        context
      })
    } else {
      return Promise.resolve(null)
    }
  }


() => {
    if (buildTimeConfig.ssr.useInitialStateFilter) {
      context.state = omit(store.state, store.state.config.ssr.initialStateFilter)
    } else {
      context.state = store.state
    }
    if (!buildTimeConfig.server.dynamicConfigReload) { // if dynamic config reload then we're sending config along with the request
      context.state = omit(store.state, ['config'])
    } else {
      const excludeFromConfig = buildTimeConfig.server.dynamicConfigExclude
      const includeFromConfig = buildTimeConfig.server.dynamicConfigInclude
      console.log(excludeFromConfig, includeFromConfig)
      if (includeFromConfig && includeFromConfig.length > 0) {
        context.state.config = pick(context.state.config, includeFromConfig)
      }
      if (excludeFromConfig && excludeFromConfig.length > 0) {
        context.state.config = omit(context.state.config, excludeFromConfig)
      }
    }
    resolve(app)
  }


err => {
    _commonErrorHandler(err, reject)
  }


context => {
  return new Promise((resolve, reject) => {
    const { app, router, store } = createApp(context, context.vs && context.vs.config ? context.vs.config : buildTimeConfig)

    const meta = (app as any).$meta()
    router.push(context.url)
    context.meta = meta
    router.onReady(() => {
      context.output.cacheTags = new Set<string>()
      if (store.state.config.storeViews.multistore === true) {
        let storeCode = context.vs.storeCode // this is from http header or env variable
        if (router.currentRoute) { // this is from url
          storeCode = storeCodeFromRoute(router.currentRoute)
        }
        if (storeCode !== '' && storeCode !== null) {
          prepareStoreView(storeCode)
        }
      }
      const matchedComponents = router.getMatchedComponents()
      if (!matchedComponents.length) {
        return reject(new HttpError('No components matched', 404))
      }
      Promise.all(matchedComponents.map((Component: any) => {
        const components = Component.mixins ? Array.from(Component.mixins) : []
        union(components, [Component]).map(SubComponent => {
          if (SubComponent.preAsyncData) {
            SubComponent.preAsyncData({ store, route: router.currentRoute })
          }
        })
        if (Component.asyncData) {
          Component.asyncData({ store, route: router.currentRoute, context: context }).then((result) => { // always execute the asyncData() from the top most component first
            console.debug('Top-most asyncData executed')
            _ssrHydrateSubcomponents(components, store, router, resolve, reject, app, context)
          }).catch((err) => {
            _commonErrorHandler(err, reject)
          })
        } else {
          _ssrHydrateSubcomponents(components, store, router, resolve, reject, app, context)
        }
      }))
    }, reject)
  })
}


(resolve, reject) => {
    const { app, router, store } = createApp(context, context.vs && context.vs.config ? context.vs.config : buildTimeConfig)

    const meta = (app as any).$meta()
    router.push(context.url)
    context.meta = meta
    router.onReady(() => {
      context.output.cacheTags = new Set<string>()
      if (store.state.config.storeViews.multistore === true) {
        let storeCode = context.vs.storeCode // this is from http header or env variable
        if (router.currentRoute) { // this is from url
          storeCode = storeCodeFromRoute(router.currentRoute)
        }
        if (storeCode !== '' && storeCode !== null) {
          prepareStoreView(storeCode)
        }
      }
      const matchedComponents = router.getMatchedComponents()
      if (!matchedComponents.length) {
        return reject(new HttpError('No components matched', 404))
      }
      Promise.all(matchedComponents.map((Component: any) => {
        const components = Component.mixins ? Array.from(Component.mixins) : []
        union(components, [Component]).map(SubComponent => {
          if (SubComponent.preAsyncData) {
            SubComponent.preAsyncData({ store, route: router.currentRoute })
          }
        })
        if (Component.asyncData) {
          Component.asyncData({ store, route: router.currentRoute, context: context }).then((result) => { // always execute the asyncData() from the top most component first
            console.debug('Top-most asyncData executed')
            _ssrHydrateSubcomponents(components, store, router, resolve, reject, app, context)
          }).catch((err) => {
            _commonErrorHandler(err, reject)
          })
        } else {
          _ssrHydrateSubcomponents(components, store, router, resolve, reject, app, context)
        }
      }))
    }, reject)
  }


() => {
      context.output.cacheTags = new Set<string>()
      if (store.state.config.storeViews.multistore === true) {
        let storeCode = context.vs.storeCode // this is from http header or env variable
        if (router.currentRoute) { // this is from url
          storeCode = storeCodeFromRoute(router.currentRoute)
        }
        if (storeCode !== '' && storeCode !== null) {
          prepareStoreView(storeCode)
        }
      }
      const matchedComponents = router.getMatchedComponents()
      if (!matchedComponents.length) {
        return reject(new HttpError('No components matched', 404))
      }
      Promise.all(matchedComponents.map((Component: any) => {
        const components = Component.mixins ? Array.from(Component.mixins) : []
        union(components, [Component]).map(SubComponent => {
          if (SubComponent.preAsyncData) {
            SubComponent.preAsyncData({ store, route: router.currentRoute })
          }
        })
        if (Component.asyncData) {
          Component.asyncData({ store, route: router.currentRoute, context: context }).then((result) => { // always execute the asyncData() from the top most component first
            console.debug('Top-most asyncData executed')
            _ssrHydrateSubcomponents(components, store, router, resolve, reject, app, context)
          }).catch((err) => {
            _commonErrorHandler(err, reject)
          })
        } else {
          _ssrHydrateSubcomponents(components, store, router, resolve, reject, app, context)
        }
      }))
    }


(Component: any) => {
        const components = Component.mixins ? Array.from(Component.mixins) : []
        union(components, [Component]).map(SubComponent => {
          if (SubComponent.preAsyncData) {
            SubComponent.preAsyncData({ store, route: router.currentRoute })
          }
        })
        if (Component.asyncData) {
          Component.asyncData({ store, route: router.currentRoute, context: context }).then((result) => { // always execute the asyncData() from the top most component first
            console.debug('Top-most asyncData executed')
            _ssrHydrateSubcomponents(components, store, router, resolve, reject, app, context)
          }).catch((err) => {
            _commonErrorHandler(err, reject)
          })
        } else {
          _ssrHydrateSubcomponents(components, store, router, resolve, reject, app, context)
        }
      }


SubComponent => {
          if (SubComponent.preAsyncData) {
            SubComponent.preAsyncData({ store, route: router.currentRoute })
          }
        }


(result) => { // always execute the asyncData() from the top most component first
            console.debug('Top-most asyncData executed')
            _ssrHydrateSubcomponents(components, store, router, resolve, reject, app, context)
          }


(err) => {
            _commonErrorHandler(err, reject)
          }


data => {
        if (data.status === 200) {
          this.cities = data["body"];
        }
      }


() => {
      this.imagePreview = reader.result;
    }


@Component({
  selector: "app-configurations",
  templateUrl: "./configurations.component.html",
  styleUrls: ["./configurations.component.scss", "../tabel.scss"]
})
export class ConfigurationsComponent implements OnInit, OnDestroy {
  unit: string;
  activities: string[] = ["شاليهات"];
  // activities: string[] = ['شاليهات', 'قاعات', 'استراحات', 'قاعات_افراح', 'خدمات_حاصة', 'ضيافة', 'عروض', 'مخيمات'];

  officeData: any;
  configurationsForm: FormGroup;
  needToUpdate: boolean = true;
  isUploadNewImage = false;
  isEdit = false;
  selectedCategories: any[];
  startTime: Date = new Date();
  endTime: Date = new Date();
  isMeridian = false;
  allowArrowKeys = true;
  cities: any;
  occasions: any[];
  days = [
    {
      id: 1,
      name: "Sunday"
    },
    {
      id: 2,
      name: "Monday"
    },
    {
      id: 3,
      name: "Tuesday"
    },
    {
      id: 4,
      name: "Wednesday"
    },
    {
      id: 5,
      name: "Thursday"
    },
    {
      id: 6,
      name: "Friday"
    }
  ];
  cityPolyganOptions = {
    strokeColor: "#083478",
    fillColor: "#0c2461",
    strokeWeight: "4",
    fillOpacity: "0.5"
  };
  center: any = {
    lat: 30.044281,
    lng: 31.340002
  };
  locationValues: any[];
  imagePreview: any;
  constructor(
    @Optional() public dialogRef: MatDialog,
    private notificationService: NotificationService,
    private httpActivityService: HttpActivityService,
    private fg: FormBuilder,
    private mapConfigService: MapConfigService
  ) {}

  ngOnInit() {
    this.configurationsForm = this.fg.group({
      name: [""],
      price: [""],
      category: [""],
      sub_category: [this.fg.array([])],
      capacity: [""],
      description: [""],
      location: [""],
      logo: [""],
      email: [""],
      images: [""],
      panoramic_images: [""],
      city: [""],
      area: [""],
      occasions: [""],
      pool_exist: [""],
      pool_desc: [""],
      bathrooms: [""],
      bedroom: [""],
      kitchen: [""],
      grill_area: [""],
      water_games: [""],
      kids_games: [""],
      playground: [""],
      sound_room: [""],
      mandi_barrel: [""],
      facilities: [""]
    });
    this.initFun();
  }

  getCities() {
    this.httpActivityService.getAllCities().subscribe(
      data => {
        if (data.status === 200) {
          this.cities = data["body"];
        }
      },
      err => {
        console.log(err);
      }
    );
  }

  initFun() {
    this.getCities();
  }

  onMapReady(map) {
    this.mapConfigService.initDrawingManager(map);
  }

  selectMarker(event) {
    this.locationValues = [event.coords.lng, event.coords.lat];
  }

  editConfigurationsData() {
    this.configurationsForm.enable();
    this.isEdit = true;
  }

  equals(objOne, objTwo) {
    if (typeof objOne !== "undefined" && typeof objTwo !== "undefined") {
      return objOne === objTwo;
    }
  }

  onImagePicked(event: Event) {
    const file = (event.target as HTMLInputElement).files[0];
    if (!file) {
      return;
    }
    const mimeType = file.type;
    if (mimeType.match(/image\/*/) == null) {
      return this.notificationService.errorNotification(
        "This file is not supported, please upload image"
      );
    }
    this.configurationsForm.patchValue({ logo: file });
    this.configurationsForm.get("logo").updateValueAndValidity();
    const reader = new FileReader();
    reader.onload = () => {
      this.imagePreview = reader.result;
    };
    reader.readAsDataURL(file);
  }

  onSubmit() {
    const updateServiceWithNewImage = {
      name: this.configurationsForm["controls"].brand_name.value,
      description: this.configurationsForm["controls"].brand_desc.value,
      categories: this.selectedCategories
    };

    console.log(updateServiceWithNewImage);
  }
  ngOnDestroy() {
    // this.$destroy.next();
    // this.$destroy.complete();
  }
}


ngOnInit() {
    this.configurationsForm = this.fg.group({
      name: [""],
      price: [""],
      category: [""],
      sub_category: [this.fg.array([])],
      capacity: [""],
      description: [""],
      location: [""],
      logo: [""],
      email: [""],
      images: [""],
      panoramic_images: [""],
      city: [""],
      area: [""],
      occasions: [""],
      pool_exist: [""],
      pool_desc: [""],
      bathrooms: [""],
      bedroom: [""],
      kitchen: [""],
      grill_area: [""],
      water_games: [""],
      kids_games: [""],
      playground: [""],
      sound_room: [""],
      mandi_barrel: [""],
      facilities: [""]
    });
    this.initFun();
  }


getCities() {
    this.httpActivityService.getAllCities().subscribe(
      data => {
        if (data.status === 200) {
          this.cities = data["body"];
        }
      },
      err => {
        console.log(err);
      }
    );
  }


initFun() {
    this.getCities();
  }


onMapReady(map) {
    this.mapConfigService.initDrawingManager(map);
  }


selectMarker(event) {
    this.locationValues = [event.coords.lng, event.coords.lat];
  }


editConfigurationsData() {
    this.configurationsForm.enable();
    this.isEdit = true;
  }


equals(objOne, objTwo) {
    if (typeof objOne !== "undefined" && typeof objTwo !== "undefined") {
      return objOne === objTwo;
    }
  }


onImagePicked(event: Event) {
    const file = (event.target as HTMLInputElement).files[0];
    if (!file) {
      return;
    }
    const mimeType = file.type;
    if (mimeType.match(/image\/*/) == null) {
      return this.notificationService.errorNotification(
        "This file is not supported, please upload image"
      );
    }
    this.configurationsForm.patchValue({ logo: file });
    this.configurationsForm.get("logo").updateValueAndValidity();
    const reader = new FileReader();
    reader.onload = () => {
      this.imagePreview = reader.result;
    };
    reader.readAsDataURL(file);
  }


onSubmit() {
    const updateServiceWithNewImage = {
      name: this.configurationsForm["controls"].brand_name.value,
      description: this.configurationsForm["controls"].brand_desc.value,
      categories: this.selectedCategories
    };

    console.log(updateServiceWithNewImage);
  }


ngOnDestroy() {
    // this.$destroy.next();
    // this.$destroy.complete();
  }


export function getURLfromItem(
  item: NativeDragItem,
  filter: Function = (): boolean => true
): string {
  let url = null;
  if (item.urls) {
    url = item.urls[0];
  }
  if (item.files) {
    if (!filter(item.files[0].type)) {
      return null;
    }
    url = item.files[0].path;
  }
  return url;
}


export default function useNativeDrop<T>({
  onDrop,
  accept = [NativeTypes.FILE, NativeTypes.URL],
  filter = (): boolean => true
}: UseNativeDropParams): {
  isOver: boolean;
  canDrop: boolean;
  drop: DragElementWrapper<T>;
} {
  const [{ isOver, canDrop }, drop] = useDrop({
    accept,
    drop: (item: NativeDragItem) => onDrop(getURLfromItem(item, filter)),
    collect: monitor => ({
      isOver: monitor.isOver(),
      canDrop: monitor.canDrop()
    })
  });
  return { isOver, canDrop, drop };
}


(item: NativeDragItem) => onDrop(getURLfromItem(item, filter))


monitor => ({
      isOver: monitor.isOver(),
      canDrop: monitor.canDrop()
    })


export interface NativeDragItem extends DragObjectWithType {
  urls?: string[];
  files?: File[];
}


type UseNativeDropParams = {
  onDrop: Function;
  accept?: string[];
  filter?: Function;
}


() => {
    this.setState({
      showModal: true
    });
  }


() => {
    this.setState({
      showModal: false
    });
  }


() => {
    const { showModal } = this.state;
    const { pendingPlugins } = this.props;
    if (showModal) {
      return <ExecutePendingModal pendingPlugins={pendingPlugins} onClose={this.closeModal} />;
    }
    return null;
  }


class ExecutePendingAction extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = {
      showModal: false
    };
  }

  openModal = () => {
    this.setState({
      showModal: true
    });
  };

  closeModal = () => {
    this.setState({
      showModal: false
    });
  };

  renderModal = () => {
    const { showModal } = this.state;
    const { pendingPlugins } = this.props;
    if (showModal) {
      return <ExecutePendingModal pendingPlugins={pendingPlugins} onClose={this.closeModal} />;
    }
    return null;
  };

  render() {
    const { t } = this.props;
    return (
      <>
        {this.renderModal()}
        <Button color="primary" label={t("plugins.executePending")} action={this.openModal} />
      </>
    );
  }
}


type Props = WithTranslation & {
  pendingPlugins: PendingPlugins;
};


type State = {
  showModal: boolean;
};


render() {
    const { t } = this.props;
    return (
      <>
        {this.renderModal()}
        <Button color="primary" label={t("plugins.executePending")} action={this.openModal} />
      </>
    );
  }


t("plugins.executePending")


user => user !== null


value => {
          if(!value){
            this.router.navigateByUrl('/login').then();
            return value;
          }
          else{
            return value;
          }
        }


@Injectable({
  providedIn: 'root'
})
export class ChatGuard implements CanActivate {

  constructor(private afAuth : AngularFireAuth, private router: Router){

  }

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {

      return this.afAuth.authState.pipe(
        map(user => user !== null),
        tap(value => {
          if(!value){
            this.router.navigateByUrl('/login').then();
            return value;
          }
          else{
            return value;
          }
        })
      );
  }
}


canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {

      return this.afAuth.authState.pipe(
        map(user => user !== null),
        tap(value => {
          if(!value){
            this.router.navigateByUrl('/login').then();
            return value;
          }
          else{
            return value;
          }
        })
      );
  }


export class TableArrayProvider<T extends Record<string, unknown>> extends TableDataProvider<T> {
  rawData: Array<T>;

  constructor({ data, ...options }: TableProviderOptions & { data: Array<T> }) {
    super(options);
    this.rawData = data;
    this.data.set(this.rawData.slice(0, this.options.itemsPerPage));
  }

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async update(): Promise<void> {}

  async page(i: number): Promise<void> {
    this.data.set(
      this.rawData.slice(
        (i - 1) * this.options.itemsPerPage,
        Math.min(i * this.options.itemsPerPage, this.rawData.length),
      ),
    );
  }

  async sort(sorting: { col: string; ascending: boolean }): Promise<void> {
    console.log('[provider] sort with', sorting);
  }

  async delete(i: number): Promise<T> {
    console.log('[provider] delete item', i);
    return null;
  }
}


// eslint-disable-next-line @typescript-eslint/no-empty-function
async update(): Promise<void> {}


async page(i: number): Promise<void> {
    this.data.set(
      this.rawData.slice(
        (i - 1) * this.options.itemsPerPage,
        Math.min(i * this.options.itemsPerPage, this.rawData.length),
      ),
    );
  }


async sort(sorting: { col: string; ascending: boolean }): Promise<void> {
    console.log('[provider] sort with', sorting);
  }


async delete(i: number): Promise<T> {
    console.log('[provider] delete item', i);
    return null;
  }


() => ({ api1Data: [APIData[0]] })


() => ({ api2Data: [APIData[1]] })


data => [...data.api1Data, ...data.api2Data].map(data => data.configuration.path)


data => data.configuration.path


async (path, data) => {
        const page = [...data.api1Data, ...data.api2Data].find(el => el.configuration.path === path);

        if (!page) {
          return null;
        }

        return {
          url: path,
          content: `${page.title}\n\n${page.content}`,
        };
      }


el => el.configuration.path === path


interface PipelineData {
  api1Data: typeof APIData[0][];
  api2Data: typeof APIData[1][];
}


export interface ValidationResult {
  errors: string[];
  valid: boolean;
}


export interface FieldMeta<TValue> {
  touched: boolean;
  dirty: boolean;
  valid: boolean;
  validated: boolean;
  pending: boolean;
  initialValue?: TValue;
}


export interface FieldState<TValue = unknown> {
  value: TValue;
  touched: boolean;
  errors: string[];
}


export interface PrivateFieldComposite<TValue = unknown> {
  fid: number;
  idx: number;
  name: MaybeRef<string>;
  value: WritableRef<TValue>;
  meta: FieldMeta<TValue>;
  errors: Ref<string[]>;
  errorMessage: ComputedRef<string | undefined>;
  label?: MaybeRef<string | undefined>;
  type?: string;
  checkedValue?: MaybeRef<TValue>;
  uncheckedValue?: MaybeRef<TValue>;
  checked?: ComputedRef<boolean>;
  resetField(state?: FieldState<TValue>): void;
  handleReset(state?: FieldState<TValue>): void;
  validate(): Promise<ValidationResult>;
  handleChange(e: Event | unknown, shouldValidate?: boolean): void;
  handleBlur(e?: Event): void;
  handleInput(e?: Event | unknown): void;
  setValidationState(state: ValidationResult): void;
  setTouched(isTouched: boolean): void;
  setErrors(message: string | string[]): void;
}


export interface FormState<TValues> {
  values: TValues;
  errors: Partial<Record<keyof TValues, string | undefined>>;
  touched: Partial<Record<keyof TValues, boolean>>;
  submitCount: number;
}


export interface SetFieldValueOptions {
  force: boolean;
}


export interface FormActions<TValues extends Record<string, unknown>> {
  setFieldValue<T extends keyof TValues>(field: T, value: TValues[T], opts?: Partial<SetFieldValueOptions>): void;
  setFieldError: (field: keyof TValues, message: string | string[] | undefined) => void;
  setErrors: (fields: FormErrors<TValues>) => void;
  setValues<T extends keyof TValues>(fields: Partial<Record<T, TValues[T]>>): void;
  setFieldTouched: (field: keyof TValues, isTouched: boolean) => void;
  setTouched: (fields: Partial<Record<keyof TValues, boolean>>) => void;
  resetForm: (state?: Partial<FormState<TValues>>) => void;
}


export interface FormValidationResult<TValues> {
  valid: boolean;
  results: Partial<Record<keyof TValues, ValidationResult>>;
}


export interface SubmissionContext<TValues extends Record<string, unknown> = Record<string, unknown>>
  extends FormActions<TValues> {
  evt?: Event;
}


export interface FormContext<TValues extends Record<string, any> = Record<string, any>> extends FormActions<TValues> {
  register(field: PrivateFieldComposite): void;
  unregister(field: PrivateFieldComposite): void;
  values: TValues;
  fieldsById: ComputedRef<Record<keyof TValues, PrivateFieldComposite | PrivateFieldComposite[]>>;
  submitCount: Ref<number>;
  schema?: MaybeRef<RawFormSchema<TValues> | SchemaOf<TValues>>;
  validateSchema?: (mode: SchemaValidationMode) => Promise<FormValidationResult<TValues>>;
  validate(): Promise<FormValidationResult<TValues>>;
  validateField(field: keyof TValues): Promise<ValidationResult>;
  errorBag: Ref<FormErrorBag<TValues>>;
  setFieldErrorBag(field: string, messages: string | string[]): void;
  stageInitialValue(path: string, value: unknown): void;
  meta: ComputedRef<{
    dirty: boolean;
    touched: boolean;
    valid: boolean;
    pending: boolean;
    initialValues: TValues;
  }>;
  isSubmitting: Ref<boolean>;
  handleSubmit(cb: SubmissionHandler<TValues>): (e?: Event) => Promise<void>;
  setFieldInitialValue(path: string, value: unknown): void;
}


export interface PublicFormContext<TValues extends Record<string, any> = Record<string, any>>
  extends Omit<
    FormContext<TValues>,
    | 'register'
    | 'unregister'
    | 'fieldsById'
    | 'schema'
    | 'validateSchema'
    | 'errorBag'
    | 'setFieldErrorBag'
    | 'stageInitialValue'
    | 'setFieldInitialValue'
  > {
  errors: ComputedRef<FormErrors<TValues>>;
  handleReset: () => void;
  submitForm: (e?: unknown) => Promise<void>;
}


export type YupValidator = AnySchema | AnyObjectSchema;


export type Locator = { __locatorRef: string } & ((values: Record<string, unknown>) => unknown);


// Extracts explicit keys of an interface without index signature
// https://stackoverflow.com/questions/51465182/typescript-remove-index-signature-using-mapped-types
export type KnownKeys<T> = {
  [K in keyof T]: string extends K ? never : number extends K ? never : K;
} extends { [_ in keyof T]: infer U }
  ? U
  : never;


export type MaybeRef<T> = Ref<T> | ComputedRef<T> | T;


export type WritableRef<TValue> = Ref<TValue> | WritableComputedRef<TValue>;


export type FieldComposable<TValue = unknown> = Omit<PrivateFieldComposite<TValue>, 'idx' | 'fid'>;


export type GenericValidateFunction = (
  value: unknown,
  ctx: FieldContext
) => boolean | string | Promise<boolean | string>;


export type FormErrors<TValues extends Record<string, unknown>> = Partial<Record<keyof TValues, string | undefined>>;


export type FormErrorBag<TValues extends Record<string, unknown>> = Partial<Record<keyof TValues, string[]>>;


export type SubmissionHandler<TValues extends Record<string, unknown> = Record<string, unknown>> = (
  values: TValues,
  ctx: SubmissionContext<TValues>
) => unknown;


export type RawFormSchema<TValues> = Record<keyof TValues, string | GenericValidateFunction | Record<string, any>>;


/**
 * validated-only: only mutate the previously validated fields
 * silent: do not mutate any field
 * force: validate all fields and mutate their state
 */
export type SchemaValidationMode = 'validated-only' | 'silent' | 'force';


({
  size = 15,
  width = 21,
  height = 15,
  ...props
}: Props) => {
  if (size !== height) {
    width = width * (size / height);
    height = height * (size / height);
  }

  return (
    <Svg width={width} height={height} viewBox="0 0 21 15" {...props}>
      <Defs>
        <LinearGradient id="prefix__a" x1="50%" x2="50%" y1="0%" y2="100%">
          <Stop offset="0%" stopColor="#FFF" />
          <Stop offset="100%" stopColor="#F0F0F0" />
        </LinearGradient>
        <LinearGradient id="prefix__b" x1="50%" x2="50%" y1="0%" y2="100%">
          <Stop offset="0%" stopColor="#262626" />
          <Stop offset="100%" stopColor="#0D0D0D" />
        </LinearGradient>
        <LinearGradient id="prefix__c" x1="50%" x2="50%" y1="0%" y2="100%">
          <Stop offset="0%" stopColor="#E42038" />
          <Stop offset="100%" stopColor="#CC162C" />
        </LinearGradient>
        <LinearGradient id="prefix__d" x1="50%" x2="50%" y1="0%" y2="100%">
          <Stop offset="0%" stopColor="#47B849" />
          <Stop offset="100%" stopColor="#399E3B" />
        </LinearGradient>
      </Defs>
      <G fill="none" fillRule="evenodd">
        <Path fill="url(#prefix__a)" d="M0 0h21v15H0z" />
        <Path fill="url(#prefix__b)" d="M0 0h21v5H0z" />
        <Circle cx={10.5} cy={5.5} r={3.5} fill="url(#prefix__c)" />
        <Path fill="url(#prefix__c)" d="M0 5h21v5H0z" />
        <Path fill="url(#prefix__d)" d="M0 10h21v5H0z" />
      </G>
    </Svg>


interface Props extends SvgProps {
  size?: number;
  width?: number;
  height?: number;
}


(e) => {
                e.preventDefault();
                $("#btnPricingIndividual").addClass("btn-primary").removeClass("btn-notSelected");
                $("#btnPricingOrgs").removeClass("btn-primary").addClass("btn-notSelected");
                $("#pricingIndividuals").show(0);
                $("#pricingOrgs").hide(0);
            }


(e) => {
                e.preventDefault();
                $("#btnPricingOrgs").addClass("btn-primary").removeClass("btn-notSelected");
                $("#btnPricingIndividual").removeClass("btn-primary").addClass("btn-notSelected");
                $("#pricingIndividuals").hide(0);
                $("#pricingOrgs").show(0);
            }


class WidgetPricing {

    constructor() {
        var self = this;

        $("#btnPricingIndividual")
            .click((e) => {
                e.preventDefault();
                $("#btnPricingIndividual").addClass("btn-primary").removeClass("btn-notSelected");
                $("#btnPricingOrgs").removeClass("btn-primary").addClass("btn-notSelected");
                $("#pricingIndividuals").show(0);
                $("#pricingOrgs").hide(0);
            });

        $("#btnPricingOrgs")
            .click((e) => {
                e.preventDefault();
                $("#btnPricingOrgs").addClass("btn-primary").removeClass("btn-notSelected");
                $("#btnPricingIndividual").removeClass("btn-primary").addClass("btn-notSelected");
                $("#pricingIndividuals").hide(0);
                $("#pricingOrgs").show(0);
            });

    }

}


export function MatchShowcasePage(){

}


questionSets => {
        this.questionSets = questionSets;
        if (questionSets) {
          this.currentQuestionSet = this.getCurrentQuestionSet();
        }
      }


q => q.id


q => q.id !== question.id


q => q.id === question.id


question => question.id


qs =>
        qs.questions.find(q => selectedIds.indexOf(q.id) !== -1) !== undefined


q => selectedIds.indexOf(q.id) !== -1


@Component({
  selector: 'app-questions-browser',
  templateUrl: './app-questions-browser.component.html',
  styleUrls: ['./app-questions-browser.component.scss']
})
export class AppQuestionsBrowserComponent implements OnInit, OnDestroy {
  allQuestionsSubscription: Subscription;
  questionSets;
  currentQuestionSet;
  selectedQuestions;
  initialSelection;
  constructor(
    private questionStoreService: QuestionStoreService,
    public dialogRef: MatDialogRef<AppQuestionsBrowserComponent>,
    @Inject(MAT_DIALOG_DATA) public data: any
  ) { }

  ngOnInit() {
    this.initialSelection = this.data.selectedQuestions;
    this.selectedQuestions = this.data.selectedQuestions;
    this.questionStoreService.getAll();
    this.allQuestionsSubscription = this.questionStoreService.questions$
      .subscribe(questionSets => {
        this.questionSets = questionSets;
        if (questionSets) {
          this.currentQuestionSet = this.getCurrentQuestionSet();
        }
      });
  }

  ngOnDestroy() {
    this.allQuestionsSubscription.unsubscribe();
  }

  safeClose() {
    const noDifference = isEqual(
      this.selectedQuestions.map(q => q.id),
      this.initialSelection.map(q => q.id)
    );

    this.dialogRef.close(noDifference ? undefined : this.selectedQuestions);
  }

  toggleSelectedQuestion(question) {
    if (this.isSelectedQuestion(question)) {
      this.selectedQuestions = this.selectedQuestions.filter(
        q => q.id !== question.id
      );
    } else {
      this.selectedQuestions = [...this.selectedQuestions, question];
    }
  }

  isSelectedQuestion(question) {
    return this.selectedQuestions.find(q => q.id === question.id);
  }

  getCurrentQuestionSet() {
    const selectedIds = this.selectedQuestions.map(question => question.id);
    const questionSet = this.questionSets.find(
      qs =>
        qs.questions.find(q => selectedIds.indexOf(q.id) !== -1) !== undefined
    );
    return questionSet
      ? questionSet
      : this.questionSets.length ? this.questionSets[0] : {};
  }
}


ngOnInit() {
    this.initialSelection = this.data.selectedQuestions;
    this.selectedQuestions = this.data.selectedQuestions;
    this.questionStoreService.getAll();
    this.allQuestionsSubscription = this.questionStoreService.questions$
      .subscribe(questionSets => {
        this.questionSets = questionSets;
        if (questionSets) {
          this.currentQuestionSet = this.getCurrentQuestionSet();
        }
      });
  }


ngOnDestroy() {
    this.allQuestionsSubscription.unsubscribe();
  }


safeClose() {
    const noDifference = isEqual(
      this.selectedQuestions.map(q => q.id),
      this.initialSelection.map(q => q.id)
    );

    this.dialogRef.close(noDifference ? undefined : this.selectedQuestions);
  }


toggleSelectedQuestion(question) {
    if (this.isSelectedQuestion(question)) {
      this.selectedQuestions = this.selectedQuestions.filter(
        q => q.id !== question.id
      );
    } else {
      this.selectedQuestions = [...this.selectedQuestions, question];
    }
  }


isSelectedQuestion(question) {
    return this.selectedQuestions.find(q => q.id === question.id);
  }


getCurrentQuestionSet() {
    const selectedIds = this.selectedQuestions.map(question => question.id);
    const questionSet = this.questionSets.find(
      qs =>
        qs.questions.find(q => selectedIds.indexOf(q.id) !== -1) !== undefined
    );
    return questionSet
      ? questionSet
      : this.questionSets.length ? this.questionSets[0] : {};
  }


({ tablename }) => tablename


(rawTable: RawTable): Table => {
        return {
          name: rawTable.table_name,
          schema: rawTable.table_schema,
          comment: rawTable.table_comment,
        };
      }


({ table_name, column_name }) => ({
      table: table_name,
      column: column_name,
    })


(rawColumn): Column => {
        return {
          name: rawColumn.column_name,
          table: rawColumn.table_name,
          type: rawColumn.data_type,
          default_value: rawColumn.column_default
            ? this.parseDefaultValue(rawColumn.column_default)
            : null,
          max_length: rawColumn.character_maximum_length,
          precision: rawColumn.numeric_precision,
          scale: rawColumn.numeric_scale,
          is_nullable: rawColumn.is_nullable === 'YES',
          is_primary_key: rawColumn.is_primary === 'YES',
          has_auto_increment: rawColumn.serial !== null,
          foreign_key_column: rawColumn.referenced_column_name,
          foreign_key_table: rawColumn.referenced_table_name,

          comment: rawColumn.column_comment,
          schema: rawColumn.table_schema,
          foreign_key_schema: rawColumn.referenced_table_schema,
        };
      }


type RawTable = {
  table_name: string;
  table_schema: 'public' | string;
  table_comment: string | null;
};


type RawColumn = {
  column_name: string;
  table_name: string;
  table_schema: string;
  data_type: string;
  column_default: any | null;
  character_maximum_length: number | null;
  is_nullable: 'YES' | 'NO';
  is_primary: null | 'YES';
  numeric_precision: null | number;
  numeric_scale: null | number;
  serial: null | string;
  column_comment: string | null;
  referenced_table_schema: null | string;
  referenced_table_name: null | string;
  referenced_column_name: null | string;
};


// Postgres specific
// ===============================================================================================
/**
   * Set the schema to be used in other methods
   */
withSchema(schema: string) {
    this.schema = schema;
    this.explodedSchema = [this.schema];
    return this;
  }


/**
   * Converts Postgres default value to JS
   * Eg `'example'::character varying` => `example`
   */
parseDefaultValue(type: string) {
    if (type.startsWith('nextval(')) return null; // auto-increment

    const parts = type.split('::');

    let value = parts[0];

    if (value.startsWith("'") && value.endsWith("'")) {
      value = value.slice(1, -1);
    }

    if (parts[1] && parts[1].includes('json')) return JSON.parse(value);
    if (parts[1] && (parts[1].includes('char') || parts[1].includes('text')))
      return String(value);

    if (Number.isNaN(Number(value))) return value;

    return Number(value);
  }


// Tables
// ===============================================================================================
/**
   * List all existing tables in the current schema/database
   */
async tables() {
    const records = await this.knex
      .select<{ tablename: string }[]>('tablename')
      .from('pg_catalog.pg_tables')
      .whereIn('schemaname', this.explodedSchema);
    return records.map(({ tablename }) => tablename);
  }


/**
   * Get the table info for a given table. If table parameter is undefined, it will return all tables
   * in the current schema/database
   */
tableInfo(): Promise<Table[]>;


tableInfo(table: string): Promise<Table>;


async tableInfo(table?: string) {
    const query = this.knex
      .select(
        'table_name',
        'table_schema',
        this.knex
          .select(this.knex.raw('obj_description(oid)'))
          .from('pg_class')
          .where({ relkind: 'r' })
          .andWhere({ relname: 'table_name ' })
          .as('table_comment')
      )
      .from('information_schema.tables')
      .whereIn('table_schema', this.explodedSchema)
      .andWhere({ table_catalog: this.knex.client.database() })
      .andWhere({ table_type: 'BASE TABLE' })
      .orderBy('table_name', 'asc');

    if (table) {
      const rawTable: RawTable = await query
        .andWhere({ table_name: table })
        .limit(1)
        .first();

      return {
        name: rawTable.table_name,
        schema: rawTable.table_schema,
        comment: rawTable.table_comment,
      } as Table;
    }

    const records = await query;

    return records.map(
      (rawTable: RawTable): Table => {
        return {
          name: rawTable.table_name,
          schema: rawTable.table_schema,
          comment: rawTable.table_comment,
        };
      }
    );
  }


/**
   * Check if a table exists in the current schema/database
   */
async hasTable(table: string) {
    const subquery = this.knex
      .select()
      .from('information_schema.tables')
      .whereIn('table_schema', this.explodedSchema)
      .andWhere({ table_name: table });
    const record = await this.knex
      .select<{ exists: boolean }>(this.knex.raw('exists (?)', [subquery]))
      .first();
    return record?.exists || false;
  }