diff --git a/package.json b/package.json index 47689fd80..34ed6bb1a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vernite", - "version": "1.0.0-beta-2", + "version": "1.0.0-beta-3", "scripts": { "@------ WORKFLOW SCRIPTS --------": "", "postinstall": "husky install", @@ -8,8 +8,8 @@ "start": "yarn serve", "serve": "ng serve", "build": "yarn print \"You need to choose configuration: 'dev', 'prod' and type command like 'yarn build:dev'\" --color=yellow", - "build:prod": "ng build --stats-json --configuration=production", - "build:dev": "ng build --stats-json --configuration=dev", + "build:prod": "ng build --configuration=production", + "build:dev": "ng build --configuration=dev", "lint": "ng lint", "analyze:serve": "webpack-bundle-analyzer dist/vernite/en-US/stats.json", "analyze:build": "yarn analyze:serve -m static -O -r documentation/report/index.html", diff --git a/src/app/_main/_main.module.ts b/src/app/_main/_main.module.ts index d1324031c..1a6c74609 100644 --- a/src/app/_main/_main.module.ts +++ b/src/app/_main/_main.module.ts @@ -69,6 +69,9 @@ import { LoaderComponent } from './components/loader/loader.component'; import { ContrastColorPipe } from './pipes/contrast-color/contrast-color.pipe'; import { DateTimePickerComponent } from './components/input-date-time/date-time-picker/date-time-picker.component'; import { TimePickerComponent } from './components/input-date-time/time-picker/time-picker.component'; +import { PrivacyPolicyPage } from './pages/privacy-policy/privacy-policy.page'; +import { TermsAndConditionsPage } from './pages/terms-and-conditions/terms-and-conditions.page'; +import { DateTimeByPreferencesPipe } from './pipes/date-time-by-preferences/date-time-by-preferences.pipe'; import { SidebarEntryComponent } from './components/sidebar-navigation/sidebar-entry/sidebar-entry.component'; import { ColorPipe } from './pipes/color/color.pipe'; import { PillComponent } from './components/pill/pill.component'; @@ -179,6 +182,7 @@ const ngModuleConfig = { DayOfWeekPipe, DayjsPipe, DateByPreferencesPipe, + DateTimeByPreferencesPipe, TabsComponent, TabComponent, InputColorComponent, @@ -194,6 +198,8 @@ const ngModuleConfig = { ColorPipe, CollapsableDirective, ReportBugDialog, + TermsAndConditionsPage, + PrivacyPolicyPage, ], providers: [ /*============================================= diff --git a/src/app/_main/components/input-date-time/date-picker/date-picker.component.ts b/src/app/_main/components/input-date-time/date-picker/date-picker.component.ts index 233a93452..f83070df0 100644 --- a/src/app/_main/components/input-date-time/date-picker/date-picker.component.ts +++ b/src/app/_main/components/input-date-time/date-picker/date-picker.component.ts @@ -4,6 +4,7 @@ import { DaysGrid, CalendarDay } from '../date-picker.model'; import { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons'; import { ControlAccessor } from '@main/classes/control-accessor/control-accessor.class'; import { unixTimestamp } from '../../../interfaces/date.interface'; +import { weekdaysShort } from '@main/libs/localization/weekdays.localization.lib'; /** * Date picker component @@ -17,7 +18,7 @@ export class DatePickerComponent extends ControlAccessor i /** * First day of week */ - @Input() firstDayOfWeek = 1; + @Input() firstDayOfWeek = dayjs.localeData().firstDayOfWeek(); /** * Flag to hide today button @@ -34,10 +35,7 @@ export class DatePickerComponent extends ControlAccessor i monthNames = dayjs.months(); /** Weekday names */ - weekdaysShort = [ - ...dayjs.weekdaysShort().slice(this.firstDayOfWeek), - ...dayjs.weekdaysShort().slice(0, this.firstDayOfWeek), - ]; + weekdaysShort = weekdaysShort(); /** @ignore */ faChevronLeft = faChevronLeft; diff --git a/src/app/_main/components/main-view/main-view.component.html b/src/app/_main/components/main-view/main-view.component.html index ec78f1708..ab513fbfe 100644 --- a/src/app/_main/components/main-view/main-view.component.html +++ b/src/app/_main/components/main-view/main-view.component.html @@ -15,4 +15,4 @@ - +{{ version }} diff --git a/src/app/_main/components/main-view/main-view.component.ts b/src/app/_main/components/main-view/main-view.component.ts index 8709d0956..957bf6a8b 100644 --- a/src/app/_main/components/main-view/main-view.component.ts +++ b/src/app/_main/components/main-view/main-view.component.ts @@ -4,6 +4,7 @@ import { environment } from 'src/environments/environment'; import { RouterExtensionsService } from '@main/services/router-extensions/router-extensions.service'; import { AuthService } from '../../../auth/services/auth/auth.service'; import { ProtoService } from '../../services/proto/proto.service'; +import { UserService } from '../../../auth/services/user/user.service'; /** * Main view component @@ -30,6 +31,7 @@ export class MainViewComponent implements OnInit { private routerExtensions: RouterExtensionsService, private protoService: ProtoService, private authService: AuthService, + private userService: UserService, ) {} ngOnInit() { @@ -40,6 +42,7 @@ export class MainViewComponent implements OnInit { if (!isLoggedIn) return; this.protoService.connect(); + this.userService.loadLocale(); }); } } diff --git a/src/app/_main/components/sidebar-navigation/sidebar-navigation.component.html b/src/app/_main/components/sidebar-navigation/sidebar-navigation.component.html index ad47f6147..40a94d8d2 100644 --- a/src/app/_main/components/sidebar-navigation/sidebar-navigation.component.html +++ b/src/app/_main/components/sidebar-navigation/sidebar-navigation.component.html @@ -1,5 +1,5 @@
- +
diff --git a/src/app/_main/libs/localization/weekdays.localization.lib.ts b/src/app/_main/libs/localization/weekdays.localization.lib.ts new file mode 100644 index 000000000..c41d0f114 --- /dev/null +++ b/src/app/_main/libs/localization/weekdays.localization.lib.ts @@ -0,0 +1,28 @@ +import * as dayjs from 'dayjs'; + +export function weekdays() { + const localeData = dayjs.localeData(); + + const firstDayOfWeek = localeData.firstDayOfWeek(); + const weekdays = localeData.weekdays(); + + for (let i = 0; i < firstDayOfWeek; i++) { + weekdays.push(weekdays.shift()!); + } + + return weekdays; +} + +export function weekdaysShort() { + const localeData = dayjs.localeData(); + + const firstDayOfWeek = localeData.firstDayOfWeek(); + const weekdaysShort = [...localeData.weekdaysShort()]; + + for (let i = 0; i < firstDayOfWeek; i++) { + weekdaysShort.push(weekdaysShort.shift()!); + } + + console.log(weekdaysShort); + return weekdaysShort; +} diff --git a/src/app/_main/pages/privacy-policy/privacy-policy.page.html b/src/app/_main/pages/privacy-policy/privacy-policy.page.html new file mode 100644 index 000000000..284219ff6 --- /dev/null +++ b/src/app/_main/pages/privacy-policy/privacy-policy.page.html @@ -0,0 +1,2518 @@ +
+
+ PRIVACY NOTICE +
+
+
+
+
+ Last updated January 08, 2023 +
+
+
+
+
+
+
+
+
+
+
+ This privacy notice for Aleksandra Serba, Adrian Antkowiak, Marcin Czerniak, + Bartosz Wawrzyniak ('Company', 'we', 'us', or + 'our'), describes how and why we might collect, + store, use, and/or share ('process') your information when you use our services + ('Services'), such as when you: +
+
    +
  • Visit our website at + vernite.dev, + or any website of ours that links to this privacy + notice
  • +
+
+
+
    +
  • Engage with us in other + related ways, including any sales, marketing, or events
  • +
+
+ Questions or concerns? Reading this privacy notice will + help you understand your privacy rights and choices. If you do not agree with our policies and practices, + please do not use our Services. If you still have any questions or concerns, please contact us at + contact.vernite@gmail.com. +
+
+
+
+
+
+
+
+ SUMMARY OF KEY + POINTS +
+
+
+
+
+ This summary provides key points + from our privacy notice, but you can find out more details about any of these topics by clicking the link + following each key point or by using our table of contents below to find the section you are looking for. + You can also click here to go directly to our table of + contents. +
+
+
+
+
+ What personal information do we + process? When you visit, use, or navigate our Services, we may process personal information + depending on how you interact with Aleksandra Serba, Adrian Antkowiak, Marcin Czerniak, Bartosz Wawrzyniak and + the Services, the choices you make, and the products and features you use. Click here to learn more. +
+
+
+
+
+ Do we process any sensitive personal + information? We do not process sensitive personal information. +
+
+
+
+
+ Do we receive any information from + third parties? We may receive information from public databases, marketing partners, social media + platforms, and other outside sources. Click here to learn more. +
+
+
+
+
+ How do we process your + information? We process your information to provide, improve, and administer our Services, + communicate with you, for security and fraud prevention, and to comply with law. We may also process your + information for other purposes with your consent. We process your information only when we have a valid legal + reason to do so. Click here to learn more. +
+
+
+
+
+ In what situations and with which + parties do we share personal information? We may share information in specific situations and with + specific third parties. Click here to learn more. +
+
+
+
+
+ How do we keep your information + safe? We have organisational and technical processes and procedures in place to protect your + personal information. However, no electronic transmission over the internet or information storage technology + can be guaranteed to be 100% secure, so we cannot promise or guarantee that hackers, cybercriminals, or other + unauthorised third parties will not be able to defeat our security and improperly collect, access, steal, or + modify your information. Click here to learn more. +
+
+
+
+
+ What are your rights? + Depending on where you are located geographically, the applicable privacy law may mean you have certain rights + regarding your personal information. Click here to learn more. +
+
+
+
+
+ How do you exercise your + rights? The easiest way to exercise your rights is by filling out our data subject request form + available here, or by contacting us. We will consider and act + upon any request in accordance with applicable data protection laws. +
+
+
+
+
+ Want to learn more about what Aleksandra Serba, + Adrian Antkowiak, Marcin Czerniak, Bartosz Wawrzyniak does with any information we collect? + Click here to review the notice in full. +
+
+
+
+
+
+
+
+ TABLE OF + CONTENTS +
+
+
+
+
+ 1. WHAT INFORMATION DO WE COLLECT? +
+
+ 2. HOW DO WE PROCESS YOUR INFORMATION? +
+
+ 3. WHAT + LEGAL BASES DO WE RELY ON TO PROCESS YOUR PERSONAL INFORMATION? +
+
+ 4. WHEN AND WITH WHOM DO WE SHARE YOUR PERSONAL + INFORMATION? +
+
+ 5. DO WE USE COOKIES AND OTHER TRACKING TECHNOLOGIES? +
+
+ 6. HOW LONG DO WE KEEP YOUR INFORMATION? +
+
+ 7. HOW DO WE KEEP YOUR INFORMATION SAFE? +
+
+ 8. DO WE COLLECT INFORMATION FROM MINORS? +
+
+ 9. WHAT ARE YOUR PRIVACY RIGHTS? +
+
+ 10. + CONTROLS FOR DO-NOT-TRACK FEATURES +
+
+ 11. DO CALIFORNIA RESIDENTS HAVE SPECIFIC PRIVACY RIGHTS? +
+
+ 12. DO WE MAKE UPDATES TO THIS NOTICE? +
+
+ 13. HOW CAN YOU + CONTACT US ABOUT THIS NOTICE? +
+
+ 14. + HOW CAN YOU + REVIEW, UPDATE, + OR DELETE THE DATA WE COLLECT FROM YOU? +
+
+
+
+
+
+
+
+ 1. WHAT INFORMATION DO WE + COLLECT? +
+
+
+
+
+ Personal + information you disclose to us +
+
+
+
+
+
+ In + Short: We collect personal information + that you provide to us. +
+
+
+
+
+
+ We collect personal + information that you voluntarily provide to us when you register on the Services, express an interest in obtaining information + about us or our products and Services, when you participate in activities on the Services, or otherwise + when you contact us. +
+
+
+
+
+
+ Personal + Information Provided by You. The personal information that we collect depends on the context of + your interactions with us and the Services, the choices you make, and the products and features you use. The + personal information we collect may include the following: +
+
    +
  • names +
  • +
+
+
    +
  • email + addresses
  • +
+
+
    +
  • usernames
  • +
+
+
    +
  • passwords
  • +
+
+
+ Sensitive Information. We do + not process sensitive information. +
+
+
+
+
+
+ All personal information + that you provide to us must be true, complete, and accurate, and you must notify us of any changes to such + personal information. +
+
+
+
+
+
+ Information collected from other sources +
+
+
+
+
+
+ In + Short: We may collect limited data from public databases, marketing + partners, and other outside sources. +
+
+
+
+
+
+ In order to enhance our + ability to provide relevant marketing, offers, and services to you and update our records, we may obtain + information about you from other sources, such as public databases, joint marketing partners, affiliate + programs, data providers, and from other third parties. + This information includes mailing addresses, job titles, email addresses, phone numbers, intent data (or + user behaviour data), Internet Protocol (IP) addresses, social media profiles, social media URLs, and custom + profiles, for purposes of targeted advertising and event promotion. +
+
+
+
+
+
+ 2. HOW DO WE PROCESS YOUR + INFORMATION? +
+
+
+
+
+
+ In + Short: We process your information to provide, improve, and administer + our Services, communicate with you, for security and fraud prevention, and to comply with law. We + may also process your information for other purposes with your + consent. +
+
+
+
+
+
+ We process your + personal information for a variety of reasons, depending on how you interact with our Services, + including: +
+
    +
  • To facilitate + account creation and authentication and otherwise manage user accounts. We may process + your information so you can create and log in to your account, as well as keep your account in working + order.
  • +
+
+
+
+
+
+
+
+
+

+

+

+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
    +
  • To save or protect an + individual's vital interest. We may process your + information when necessary to save or protect an individual’s + vital interest, such as to prevent harm.
  • +
+
+
+
+
+
+ 3. WHAT LEGAL BASES DO WE RELY ON + TO PROCESS YOUR INFORMATION? +
+
+
+
+
+ In Short: We + only process your personal information when we believe it is + necessary and we have a valid legal reason (i.e. legal basis) to + do so under applicable law, like with your consent, to comply + with laws, to provide you with services to enter into or fulfil + our contractual obligations, to protect your rights, or to + fulfil our legitimate business interests. +
+
+
+
+
+ The + General Data Protection Regulation (GDPR) and UK GDPR require us + to explain the valid legal bases we rely on in order to process + your personal information. As such, we may rely on the following + legal bases to process your personal information: +
+
    +
  • + Consent. We + may process your information if you have given us permission + (i.e. consent) to use your personal information for a specific + purpose. You can withdraw your consent at any time. + Click here to learn more. +
  • +
+
+
+
    +
  • Legal Obligations. + We may process your information where we believe it is + necessary for compliance with our legal obligations, such as + to cooperate with a law enforcement body or regulatory agency, + exercise or defend our legal rights, or disclose your + information as evidence in litigation in which we are + involved.
  • +
+
+
    +
  • Vital Interests. We + may process your information where we believe it is necessary + to protect your vital interests or the vital interests of a + third party, such as situations involving potential threats to + the safety of any person.
  • +
+
+
+
+
+
+ 4. WHEN AND WITH WHOM DO + WE SHARE YOUR PERSONAL + INFORMATION? +
+
+
+
+
+ In + Short: We may share information in + specific situations described in this section and/or with + the following third parties. +
+
+
+
+
+
+ We may need to share your personal + information in the following situations: +
+
    +
  • Business + Transfers. We may share or transfer your + information in connection with, or during negotiations of, any + merger, sale of company assets, financing, or acquisition of + all or a portion of our business to another + company.
  • +
+
+
+
+
+
+
+
+
+
+
+ 5. DO WE USE + COOKIES AND OTHER TRACKING + TECHNOLOGIES? +
+
+
+
+
+ In + Short: We may use cookies + and other tracking technologies to collect and + store your information. +
+
+
+
+
+ We may use cookies and + similar tracking technologies (like web beacons and + pixels) to access or store information. Specific + information about how we use such technologies and + how you can refuse certain cookies is set out in our + Cookie Notice. +
+
+
+
+
+ 6. HOW LONG DO + WE KEEP YOUR + INFORMATION? +
+
+
+
+
+ In + Short: We keep your + information for as long as necessary to fulfil the + purposes outlined in this privacy notice unless + otherwise required by + law. +
+
+
+
+
+ We will only keep your + personal information for as long as it is necessary + for the purposes set out in this privacy notice, + unless a longer retention period is required or + permitted by law (such as tax, accounting, or other + legal requirements). No purpose in this notice will + require us keeping your personal information for + longer than the period of time in which users have + an account with us. +
+
+
+
+
+ When we have no + ongoing legitimate business need to process your + personal information, we will either delete or + anonymise such information, or, if this is not + possible (for example, because your personal + information has been stored in backup archives), + then we will securely store your personal + information and isolate it from any further + processing until deletion is + possible. +
+
+
+
+
+ 7. HOW DO WE + KEEP YOUR INFORMATION + SAFE? +
+
+
+
+
+ In + Short: We aim to protect + your personal information through a system of + organisational and technical security + measures. +
+
+
+
+
+ We have implemented + appropriate and reasonable technical and + organisational security measures designed to protect + the security of any personal information we process. + However, despite our safeguards and efforts to + secure your information, no electronic transmission + over the Internet or information storage technology + can be guaranteed to be 100% secure, so we cannot + promise or guarantee that hackers, cybercriminals, + or other unauthorised third parties will not be able + to defeat our security and improperly collect, + access, steal, or modify your information. Although + we will do our best to protect your personal + information, transmission of personal information to + and from our Services is at your own risk. You + should only access the Services within a secure + environment. +
+
+
+
+
+ 8. DO WE + COLLECT INFORMATION FROM + MINORS? +
+
+
+
+
+ In + Short: We do not + knowingly collect data from or market to children + under 18 years of age. +
+
+
+
+
+ We do not knowingly + solicit data from or market to children under 18 + years of age. By using the Services, you represent + that you are at least 18 or that you are the parent + or guardian of such a minor and consent to such + minor dependent’s use of the Services. If we learn + that personal information from users less than 18 + years of age has been collected, we will deactivate + the account and take reasonable measures to promptly + delete such data from our records. If you become + aware of any data we may have collected from + children under age 18, please contact us at contact.vernite@gmail.com. +
+
+
+
+
+ 9. WHAT ARE + YOUR PRIVACY + RIGHTS? +
+
+
+
+
+ In + Short: In some regions, + such as the European Economic Area (EEA) and + United Kingdom (UK), you have rights that allow + you greater access to and control over your + personal information. You + may review, change, or terminate your account at + any time. +
+
+
+
+
+ In some regions (like + the EEA and UK), you have certain rights under + applicable data protection laws. These may include + the right (i) to request access and obtain a copy of + your personal information, (ii) to request + rectification or erasure; (iii) to restrict the + processing of your personal information; and (iv) if + applicable, to data portability. In certain + circumstances, you may also have the right to object + to the processing of your personal information. You + can make such a request by contacting us by using + the contact details provided in the section + 'HOW CAN YOU CONTACT + US ABOUT THIS + NOTICE?' + below. +
+
+
+
+
+ We will consider and + act upon any request in accordance with applicable + data protection laws. +
+
+   +
+
+ If you are located in + the EEA or UK and you believe we are unlawfully + processing your personal information, you also have + the right to complain to your local data protection + supervisory authority. You can find their contact + details here: https://ec.europa.eu/justice/data-protection/bodies/authorities/index_en.htm. +
+
+
+
+
+ If you are located in + Switzerland, the contact details for the data + protection authorities are available here: https://www.edoeb.admin.ch/edoeb/en/home.html. +
+
+
+
+
+ Withdrawing + your consent: If we are relying on + your consent to process your personal information, + you have the right to withdraw your consent at any + time. You can withdraw your consent at any time by + contacting us by using the contact details provided + in the section 'HOW CAN YOU CONTACT + US ABOUT THIS + NOTICE?' below or updating + your preferences. +
+
+
+
+
+ However, please note + that this will not affect the lawfulness of the + processing before its withdrawal nor, will it affect + the processing of your personal information conducted + in reliance on lawful processing grounds other than + consent. +
+
+
+
+
+ Account + Information +
+
+
+
+
+ If you would at any time like + to review or change the information in your account or + terminate your account, you can: +
+
    +
  • Log in to your account + settings and update your user account. +
  • +
+
+
+ Upon your request to + terminate your account, we will deactivate or delete + your account and information from our active + databases. However, we may retain some information in + our files to prevent fraud, troubleshoot problems, + assist with any investigations, enforce our legal + terms and/or comply with applicable legal + requirements. +
+
+
+
+
+ Cookies and + similar technologies: Most Web + browsers are set to accept cookies by default. If + you prefer, you can usually choose to set your + browser to remove cookies and to reject cookies. If + you choose to remove cookies or reject cookies, this + could affect certain features or services of our + Services. To opt out of interest-based advertising + by advertisers on our Services visit http://www.aboutads.info/choices/. +
+
+
+
+
+ If you have questions or + comments about your privacy rights, you may email us + at contact.vernite@gmail.com. +
+
+
+
+
+ 10. CONTROLS + FOR DO-NOT-TRACK + FEATURES +
+
+
+
+
+ Most web browsers and + some mobile operating systems and mobile + applications include a Do-Not-Track ('DNT') feature + or setting you can activate to signal your privacy + preference not to have data about your online + browsing activities monitored and collected. At this + stage no uniform technology standard for recognising + and implementing DNT signals has been finalised. As + such, we do not currently respond to DNT browser + signals or any other mechanism that automatically + communicates your choice not to be tracked online. + If a standard for online tracking is adopted that we + must follow in the future, we will inform you about + that practice in a revised version of this privacy + notice. +
+
+
+
+
+ 11. DO + CALIFORNIA RESIDENTS HAVE SPECIFIC PRIVACY + RIGHTS? +
+
+
+
+
+ In + Short: Yes, if you are a + resident of California, you are granted specific + rights regarding access to your personal + information. +
+
+
+
+
+ California Civil Code + Section 1798.83, also known as the 'Shine The Light' + law, permits our users who are California residents + to request and obtain from us, once a year and free + of charge, information about categories of personal + information (if any) we disclosed to third parties + for direct marketing purposes and the names and + addresses of all third parties with which we shared + personal information in the immediately preceding + calendar year. If you are a California resident and + would like to make such a request, please submit + your request in writing to us using the contact + information provided below. +
+
+
+
+
+ If you are under 18 + years of age, reside in California, and have a + registered account with Services, you have the right + to request removal of unwanted data that you + publicly post on the Services. To request removal of + such data, please contact us using the contact + information provided below and include the email + address associated with your account and a statement + that you reside in California. We will make sure the + data is not publicly displayed on the Services, but + please be aware that the data may not be completely + or comprehensively removed from all our systems + (e.g. backups, etc.). +
+
+
+
+
+ CCPA Privacy + Notice +
+
+
+
+
+
+ The California + Code of Regulations defines a 'resident' + as: +
+
+
+
+
+
+ (1) every individual + who is in the State of California for other than a + temporary or transitory purpose + and +
+
+ (2) every individual + who is domiciled in the State of California who is + outside the State of California for a temporary or + transitory purpose +
+
+
+
+
+ All other individuals + are defined as 'non-residents'. +
+
+
+
+
+ If this definition of + 'resident' applies to you, we must adhere to certain + rights and obligations regarding your personal + information. +
+
+
+
+
+ What + categories of personal information do we + collect? +
+
+
+
+
+ We have collected the + following categories of personal information in the + past twelve (12) months: +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Category + + Examples + + Collected +
+
+ A. + Identifiers +
+
+
+ Contact + details, such as real name, alias, postal + address, telephone or mobile contact number, + unique personal identifier, online + identifier, Internet Protocol address, email + address, and account + name +
+
+
+
+
+
+ NO +
+
+
+
+
+
+ B. Personal + information categories listed in the + California Customer Records + statute +
+
+
+ Name, contact + information, education, employment, + employment history, and financial + information +
+
+
+
+
+
+ NO +
+
+
+
+
+
+ C. Protected + classification characteristics under + California or federal + law +
+
+
+ Gender and + date of birth +
+
+
+
+
+
+ NO +
+
+
+
+
+
+ D. Commercial + information +
+
+
+ Transaction + information, purchase history, financial + details, and payment + information +
+
+
+
+
+
+ NO +
+
+
+
+
+
+ E. Biometric + information +
+
+
+ Fingerprints + and voiceprints +
+
+
+
+
+
+ NO +
+
+
+
+
+
+ F. Internet or + other similar network + activity +
+
+
+ Browsing + history, search history, online behaviour, + interest data, and interactions with our and + other websites, applications, systems, and + advertisements +
+
+
+
+
+
+ NO +
+
+
+
+
+
+ G. Geolocation + data +
+
+
+ Device + location +
+
+
+
+
+
+ YES +
+
+
+
+
+
+ H. Audio, + electronic, visual, thermal, olfactory, or + similar information +
+
+
+ Images and + audio, video or call recordings created in + connection with our business + activities +
+
+
+
+
+
+ NO +
+
+
+
+
+
+ I. + Professional or employment-related + information +
+
+
+ Business + contact details in order to provide you our + Services at a business level or job title, + work history, and professional + qualifications if you apply for a job with + us +
+
+
+
+
+
+ NO +
+
+
+
+
+
+ J. Education + Information +
+
+
+ Student + records and directory + information +
+
+
+
+
+
+ NO +
+
+
+
+
+
+ K. Inferences + drawn from other personal + information +
+
+
+ Inferences + drawn from any of the collected personal + information listed above to create a profile + or summary about, for example, an + individual’s preferences and + characteristics +
+
+
+
+
+
+ NO +
+
+
+
+
+ L. Sensitive + Personal Information + + +
+ NO
+
+
+
+
+
+
+
+ We will use and retain + the collected personal information as needed to provide + the Services or for: +
+
+
+
+
+
+
    +
  • Category G - + As long as the user has an account with + us
  • +
+
+
+
+
+
+
+
+ We + may also collect other + personal information outside + of these categories through + instances where you interact + with us in person, online, or + by phone or mail in the + context + of: +
+
    +
  • Receiving + help through our customer + support + channels; +
  • +
+
    +
  • Participation + in customer surveys or + contests; + and +
  • +
+
    +
  • Facilitation + in the delivery of our + Services and to respond to + your + inquiries. +
  • +
+
+ How + do we use and share your + personal + information? +
+
+
+
+
+ More + information about our + data collection and + sharing practices can be + found in this privacy + notice. +
+
+
+
+
+ You + may contact us by email + at contact.vernite@gmail.com, + or + by referring to the contact + details at the bottom of this + document. +
+
+
+
+
+ If + you are using an authorised + agent to exercise your right + to opt out we may deny a + request if the authorised + agent does not submit proof + that they have been validly + authorised to act on your + behalf. +
+
+
+
+
+ Will + your information be shared + with anyone + else? +
+
+
+
+
+ We + may disclose your personal + information with our service + providers pursuant to a + written contract between us + and each service provider. + Each service provider is a + for-profit entity that + processes the information on + our behalf, following the same + strict privacy protection + obligations mandated by the + CCPA. +
+
+
+
+
+ We + may use your personal + information for our own + business purposes, such as for + undertaking internal research + for technological development + and demonstration. This is not + considered to be 'selling' of + your personal + information. +
+
+
+
+
+ Aleksandra + Serba, Adrian Antkowiak, + Marcin Czerniak, Bartosz + Wawrzyniak has + not disclosed, sold, or shared + any personal information to + third parties for a business + or commercial purpose in the + preceding twelve (12) months. + Aleksandra + Serba, Adrian Antkowiak, + Marcin Czerniak, Bartosz + Wawrzyniak will + not sell or share personal + information in the future + belonging to website visitors, + users, and other + consumers. +
+
+
+
+
+ Your + rights with respect to your + personal + data +
+
+
+
+
+ Right + to request deletion of the + data — Request to + delete +
+
+
+
+
+ You + can ask for the deletion of + your personal information. If + you ask us to delete your + personal information, we will + respect your request and + delete your personal + information, subject to + certain exceptions provided by + law, such as (but not limited + to) the exercise by another + consumer of his or her right + to free speech, our compliance + requirements resulting from a + legal obligation, or any + processing that may be + required to protect against + illegal + activities. +
+
+
+
+
+ Right + to be informed — Request to + know +
+
+
+
+
+ Depending + on the circumstances, you have + a right to + know: +
+
    +
  • whether + we collect and use your + personal + information; +
  • +
+
    +
  • the + categories of personal + information that we + collect; +
  • +
+
    +
  • the + purposes for which the + collected personal + information is + used; +
  • +
+
    +
  • whether + we sell or share personal + information to third + parties; +
  • +
+
    +
  • the + categories of personal + information that we sold, + shared, or disclosed for a + business + purpose; +
  • +
+
    +
  • the + categories of third parties + to whom the personal + information was sold, + shared, or disclosed for a + business + purpose; +
  • +
+
    +
  • the + business or commercial + purpose for collecting, + selling, or sharing personal + information; + and +
  • +
+
+
    +
  • the + specific pieces of personal + information we collected about + you.
  • +
+
+ In + accordance with applicable + law, we are not obligated to + provide or delete consumer + information that is + de-identified in response to a + consumer request or to + re-identify individual data to + verify a consumer + request. +
+
+
+
+
+ Right + to Non-Discrimination for + the Exercise of a Consumer’s + Privacy + Rights +
+
+
+
+
+ We + will not discriminate against + you if you exercise your + privacy + rights. +
+
+
+
+
+ Right + to Limit Use and Disclosure of + Sensitive Personal + Information +
+
+
+
+
+
+ We + do not process consumer's + sensitive personal + information. +
+
+
+
+
+
+ Verification + process +
+
+
+
+
+ Upon + receiving your request, we + will need to verify your + identity to determine you are + the same person about whom we + have the information in our + system. These verification + efforts require us to ask you + to provide information so that + we can match it with + information you have + previously provided us. For + instance, depending on the + type of request you submit, we + may ask you to provide certain + information so that we can + match the information you + provide with the information + we already have on file, or we + may contact you through a + communication method (e.g. + phone or email) that you have + previously provided to us. We + may also use other + verification methods as the + circumstances + dictate. +
+
+
+
+
+ We + will only use personal + information provided in your + request to verify your + identity or authority to make + the request. To the extent + possible, we will avoid + requesting additional + information from you for the + purposes of verification. + However, if we cannot verify + your identity from the + information already maintained + by us, we may request that you + provide additional information + for the purposes of verifying + your identity and for security + or fraud-prevention purposes. + We will delete such + additionally provided + information as soon as we + finish verifying + you. +
+
+
+
+
+ Other + privacy + rights +
+
    +
  • You + may object to the processing + of your personal + information. +
  • +
+
    +
  • You + may request correction of + your personal data if it is + incorrect or no longer + relevant, or ask to restrict + the processing of the + information. +
  • +
+
    +
  • You + can designate an authorised + agent to make a request + under the CCPA on your + behalf. We may deny a + request from an authorised + agent that does not submit + proof that they have been + validly authorised to act on + your behalf in accordance + with the + CCPA. +
  • +
+
    +
  • You + may request to opt out from + future selling or sharing of + your personal information to + third parties. Upon + receiving an opt-out + request, we will act upon + the request as soon as + feasibly possible, but no + later than fifteen (15) days + from the date of the request + submission. +
  • +
+
+ To + exercise these rights, you can + contact us by + email at + contact.vernite@gmail.com, + or + by referring to the contact + details at the bottom of this + document. If you have a complaint + about how we handle your data, we + would like to hear from + you. +
+
+
+
+
+ 12. + DO WE MAKE UPDATES TO + THIS + NOTICE? +
+
+
+
+
+ In + Short: Yes, + we will update this notice + as necessary to stay + compliant with relevant + laws. +
+
+
+
+
+ We + may update this privacy notice + from time to time. The updated + version will be indicated by + an updated 'Revised' date and + the updated version will be + effective as soon as it is + accessible. If we make + material changes to this + privacy notice, we may notify + you either by prominently + posting a notice of such + changes or by directly sending + you a notification. We + encourage you to review this + privacy notice frequently to + be informed of how we are + protecting your + information. +
+
+
+
+
+ 13. + HOW CAN YOU CONTACT US + ABOUT THIS + NOTICE? +
+
+
+
+
+ If + you have questions or comments + about this notice, you may + email + us at + contact.vernite@gmail.com or + by post + to: +
+
+
+
+
+ Aleksandra + Serba, Adrian + Antkowiak, Marcin + Czerniak, Bartosz + Wawrzyniak +
+
+ __________ +
+
+ __________ +
+
+ Poland +
+
+
+
+
+ 14. + HOW CAN YOU REVIEW, + UPDATE, OR DELETE THE + DATA WE COLLECT FROM + YOU? +
+
+
+
+
+ Based + on the applicable laws of your + country, you may have the + right to request access to the + personal information we + collect from you, change that + information, or delete it. To + request to review, update, or + delete your personal + information, please submit a + request form by + clicking here. +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/_main/pages/privacy-policy/privacy-policy.page.scss b/src/app/_main/pages/privacy-policy/privacy-policy.page.scss new file mode 100644 index 000000000..d409f7137 --- /dev/null +++ b/src/app/_main/pages/privacy-policy/privacy-policy.page.scss @@ -0,0 +1,4 @@ +:host { + display: block; + padding: 3rem; +} diff --git a/src/app/_main/pages/privacy-policy/privacy-policy.page.ts b/src/app/_main/pages/privacy-policy/privacy-policy.page.ts new file mode 100644 index 000000000..6b33f1eab --- /dev/null +++ b/src/app/_main/pages/privacy-policy/privacy-policy.page.ts @@ -0,0 +1,25 @@ +import { Component, OnInit } from '@angular/core'; +import { Router, NavigationEnd } from '@angular/router'; + +@Component({ + selector: 'app-privacy-policy', + templateUrl: './privacy-policy.page.html', + styleUrls: ['./privacy-policy.page.scss'], +}) +export class PrivacyPolicyPage implements OnInit { + constructor(private router: Router) {} + + ngOnInit() { + this.router.events.subscribe((event) => { + if (event instanceof NavigationEnd) { + const tree = this.router.parseUrl(this.router.url); + if (tree.fragment) { + const element = document.querySelector('#' + tree.fragment); + if (element) { + element.scrollIntoView(); + } + } + } + }); + } +} diff --git a/src/app/_main/pages/terms-and-conditions/terms-and-conditions.page.html b/src/app/_main/pages/terms-and-conditions/terms-and-conditions.page.html new file mode 100644 index 000000000..aeb46695b --- /dev/null +++ b/src/app/_main/pages/terms-and-conditions/terms-and-conditions.page.html @@ -0,0 +1,1623 @@ +
+
+ +
+
+
+
+
+ These + Terms of Use constitute a legally binding agreement made between you, whether personally or on behalf of an + entity (“you”) and Aleksandra Serba, Adrian Antkowiak, Marcin Czerniak, Bartosz Wawrzyniak + ("Company," “we," “us," or “our”), + concerning your access to and use of the https://vernite.dev website as well as any other media form, media channel, + mobile website or mobile application related, linked, or otherwise connected thereto (collectively, the + “Site”). We + are registered in Poland + and have our registered office at __________, __________. + You agree that by accessing the Site, you have read, understood, and agreed to be bound by all of these Terms of + Use. IF YOU DO NOT AGREE WITH ALL OF THESE TERMS OF USE, THEN YOU ARE EXPRESSLY PROHIBITED FROM USING THE SITE + AND YOU MUST DISCONTINUE USE IMMEDIATELY. +
+
+
+
+
+
+
+ Supplemental + terms and conditions or documents that may be posted on the Site from time to time are hereby expressly + incorporated herein by reference. We reserve the right, in our sole discretion, to make changes or + modifications to these Terms of Use from time to time. We will alert you about any changes by updating the + “Last updated” date of these Terms of Use, and you waive any right to receive specific notice of each such + change. Please ensure that you check the applicable Terms every time you use our Site so that you understand + which Terms apply. You will be subject to, and will be deemed to have been made aware of and to have accepted, + the changes in any revised Terms of Use by your continued use of the Site after the date such revised Terms of + Use are posted. +
+
+
+
+
+
+
+ The + information provided on the Site is not intended for distribution to or use by any person or entity in any + jurisdiction or country where such distribution or use would be contrary to law or regulation or which would + subject us to any registration requirement within such jurisdiction or country. Accordingly, those persons who + choose to access the Site from other locations do so on their own initiative and are solely responsible for + compliance with local laws, if and to the extent local laws are applicable. +
+
+
+
+
+
+
+
+ The + Site is not tailored to comply with industry-specific regulations (Health Insurance Portability and + Accountability Act (HIPAA), Federal Information Security Management Act (FISMA), etc.), so if your + interactions would be subjected to such laws, you may not use this Site. You may not use the Site in a way + that would violate the Gramm-Leach-Bliley Act (GLBA). +
+
+
+
+
+
+
+ The Site is + intended for users who are at least 18 years old. Persons under the age of 18 are not permitted to use or + register for the Site. +
+
+
+
+
+
+
+
+
+
+ 2. INTELLECTUAL + PROPERTY RIGHTS +
+
+
+
+
+
+
+ Unless + otherwise indicated, the Site is our proprietary property and all source code, databases, functionality, + software, website designs, audio, video, text, photographs, and graphics on the Site (collectively, the + “Content”) and the trademarks, service marks, and logos contained therein (the “Marks”) are owned or + controlled by us or licensed to us, and are protected by copyright and trademark laws and various other + intellectual property rights and unfair competition laws of the United States, international copyright laws, + and international conventions. The Content and the Marks are provided on the Site “AS IS” for your information + and personal use only. Except as expressly provided in these Terms of Use, no part of the Site and no Content + or Marks may be copied, reproduced, aggregated, republished, uploaded, posted, publicly displayed, encoded, + translated, transmitted, distributed, sold, licensed, or otherwise exploited for any commercial purpose + whatsoever, without our express prior written permission. +
+
+
+
+
+
+
+ Provided + that you are eligible to use the Site, you are granted a limited license to access and use the Site and to + download or print a copy of any portion of the Content to which you have properly gained access solely for + your personal, non-commercial use. We reserve all rights not expressly granted to you in and to the Site, the + Content and the Marks. +
+
+
+
+
+
+
+
+
+
+ 3. USER + REPRESENTATIONS +
+
+
+
+
+
+
+
+ By using the Site, you + represent and warrant that: (1) all registration information you submit will be true, + accurate, current, and complete; (2) you will maintain the accuracy of such information and + promptly update such registration information as necessary; (3) you have the legal capacity and you agree to comply + with these Terms of Use; (4) you are not a minor in the jurisdiction in which you + reside; (5) you will not access the Site through automated or + non-human means, whether through a bot, script, or otherwise; (6) you will not use the Site for any illegal or unauthorized + purpose; and (7) your use of the Site will not violate any applicable law + or regulation. +
+
+
+
+
+
+
+ If you provide any information + that is untrue, inaccurate, not current, or incomplete, we have the right to suspend or terminate your + account and refuse any and all current or future use of the Site (or any portion thereof). +
+
+
+
+
+
+
+
+
+
+
+ +
+ 4. USER + REGISTRATION +
+
+
+      +
+ You may be required to register + with the Site. You agree to keep your password confidential and will be responsible for all use of your + account and password. We reserve the right to remove, reclaim, or change a username you select if we + determine, in our sole discretion, that such username is inappropriate, obscene, or otherwise + objectionable. +
+
+
+
+
+
+
+
+
+
+
+
+ +
+ 5. PROHIBITED + ACTIVITIES +
+
+
+
+
+
+
+ You may not access or use the + Site for any purpose other than that for which we make the Site available. The Site may not be used in + connection with any commercial endeavors except those that are specifically endorsed or approved by + us. +
+
+
+
+
+
+
+
+
+ As a user of the Site, you + agree not to: +
+
+
    +
  • Systematically + retrieve data or other content from the Site to create or compile, directly or indirectly, a + collection, compilation, database, or directory without written permission from us.
  • +
  • Trick, + defraud, or mislead us and other users, especially in any attempt to learn sensitive account + information such as user passwords.
  • +
  • Circumvent, + disable, or otherwise interfere with security-related features of the Site, including features + that prevent or restrict the use or copying of any Content or enforce limitations on the use of + the Site and/or the Content contained therein.
  • +
  • Disparage, + tarnish, or otherwise harm, in our opinion, us and/or the + Site.
  • +
  • Use + any information obtained from the Site in order to harass, abuse, or harm another + person.
  • +
  • Make + improper use of our support services or submit false reports of abuse or + misconduct.
  • +
  • Use + the Site in a manner inconsistent with any applicable laws or + regulations.
  • +
  • Engage + in unauthorized framing of or linking to the Site.
  • +
  • Upload + or transmit (or attempt to upload or to transmit) viruses, Trojan horses, or other material, + including excessive use of capital letters and spamming (continuous posting of repetitive text), + that interferes with any party’s uninterrupted use and enjoyment of the Site or modifies, + impairs, disrupts, alters, or interferes with the use, features, functions, operation, or + maintenance of the Site.
  • +
  • Engage + in any automated use of the system, such as using scripts to send comments or messages, or using + any data mining, robots, or similar data gathering and extraction + tools.
  • +
  • Delete + the copyright or other proprietary rights notice from any + Content.
  • +
  • Attempt + to impersonate another user or person or use the username of another + user.
  • +
  • Upload + or transmit (or attempt to upload or to transmit) any material that acts as a passive or active + information collection or transmission mechanism, including without limitation, clear graphics + interchange formats (“gifs”), 1×1 pixels, web bugs, cookies, or other similar devices (sometimes + referred to as “spyware” or “passive collection mechanisms” or + “pcms”).
  • +
  • Interfere + with, disrupt, or create an undue burden on the Site or the networks or services connected to + the Site.
  • +
  • Harass, + annoy, intimidate, or threaten any of our employees or agents engaged in providing any portion + of the Site to you.
  • +
  • Attempt + to bypass any measures of the Site designed to prevent or restrict access to the Site, or any + portion of the Site.
  • +
  • Copy + or adapt the Site’s software, including but not limited to Flash, PHP, HTML, JavaScript, or + other code.
  • +
  • Except + as permitted by applicable law, decipher, decompile, disassemble, or reverse engineer any of the + software comprising or in any way making up a part of the + Site.
  • +
  • Except + as may be the result of standard search engine or Internet browser usage, use, launch, develop, + or distribute any automated system, including without limitation, any spider, robot, cheat + utility, scraper, or offline reader that accesses the Site, or using or launching any + unauthorized script or other software.
  • +
  • Use + a buying agent or purchasing agent to make purchases on the + Site.
  • +
  • Make + any unauthorized use of the Site, including collecting usernames and/or email addresses of users + by electronic or other means for the purpose of sending unsolicited email, or creating user + accounts by automated means or under false pretenses.
  • +
  • Use + the Site as part of any effort to compete with us or otherwise use the Site and/or the Content + for any revenue-generating endeavor or commercial enterprise. +
  • +
  • Use + the Site to advertise or offer to sell goods and services. +
  • +
  • Sell + or otherwise transfer your profile.
  • +
  • Trick, defraud, or mislead other users, especially in any attempt to learn + sensitive account information such as user passwords.
  • +
  • Circumvent, disable, or otherwise interfere with security-related features. + This includes features that prevent/restrict the use of any content limits site usage.
  • +
  • Harass, abuse, or harm another person using any information obtained from + site.
  • +
  • Use the support services improperly, or submit false reports of abuse or + misconduct.
  • +
  • Use site inconsistently with any applicable laws or regulations.
  • +
  • Attempt to upload or transmit viruses, Trojan horses, or other materials + (including excessive use of capital letters and spamming) that interferes with any party's uninterrupted + use of site and its features.
  • +
  • Delete the copyright or other proprietary rights notice from any + content.
  • +
  • Impersonate another user or person or use the username of another user. +
  • +
  • Upload any materials that actively or passively collects information or acts as + a transmission mechanism (includes gifs, 1x1 pixels, web bugs, cookies, spyware, pcms, etc.)
  • +
  • Bypass measures of site designed to prevent/restrict access.
  • +
  • Decipher, decompile, disassemble, or reverse engineer any of the software that + makes up site.
  • +
  • Use site in an unauthorized way (collecting usernames, email addresses, of + users for the purpose of sending unsolicited email, or creating user accounts by automated means or + under false pretenses).
  • +
+
+ +
+
+
+
+
+
+
+
+
+
+ 6. USER + GENERATED CONTRIBUTIONS +
+
+
+
+
+
+
+ The Site may invite you to + chat, contribute to, or participate in blogs, message boards, online forums, and other functionality, and + may provide you with the opportunity to create, submit, post, display, transmit, perform, publish, + distribute, or broadcast content and materials to us or on the Site, including but not limited to text, + writings, video, audio, photographs, graphics, comments, suggestions, or personal information or other + material (collectively, "Contributions"). Contributions may be viewable by other users of the Site and + through third-party websites. As such, any Contributions you transmit may be treated as non-confidential + and non-proprietary. When you create or make available any Contributions, you thereby represent and + warrant that: +
+
    +
  • The creation, distribution, transmission, public display, or + performance, and the accessing, downloading, or copying of your Contributions do not and will not + infringe the proprietary rights, including but not limited to the copyright, patent, trademark, trade + secret, or moral rights of any third party.
  • +
  • You are the creator and owner of or have the + necessary licenses, rights, consents, releases, and permissions to use and to authorize us, the Site, + and other users of the Site to use your Contributions in any manner contemplated by the Site and these + Terms of Use.
  • +
  • You have the written consent, release, and/or + permission of each and every identifiable individual person in your Contributions to use the name or + likeness of each and every such identifiable individual person to enable inclusion and use of your + Contributions in any manner contemplated by the Site and these Terms of Use.
  • +
  • Your Contributions are not false, inaccurate, or + misleading.
  • +
  • Your Contributions are not unsolicited or unauthorized + advertising, promotional materials, pyramid schemes, chain letters, spam, mass mailings, or other forms + of solicitation.
  • +
  • Your Contributions are not obscene, lewd, lascivious, + filthy, violent, harassing, libelous, slanderous, or otherwise objectionable (as determined by + us).
  • +
  • Your Contributions do not ridicule, mock, disparage, + intimidate, or abuse anyone.
  • +
  • Your Contributions are not used to harass or threaten + (in the legal sense of those terms) any other person and to promote violence against a specific person + or class of people.
  • +
  • Your Contributions do not violate any applicable law, + regulation, or rule.
  • +
  • Your Contributions do not violate the privacy or + publicity rights of any third party.
  • +
  • Your Contributions do not violate any applicable law + concerning child pornography, or otherwise intended to protect the health or well-being of + minors.
  • +
  • Your Contributions do not include any offensive + comments that are connected to race, national origin, gender, sexual preference, or physical + handicap.
  • +
  • Your Contributions do not otherwise violate, or link to + material that violates, any provision of these Terms of Use, or any applicable law or regulation. +
  • +
+
+ Any use of the Site in + violation of the foregoing violates these Terms of Use and may result in, among other things, termination + or suspension of your rights to use the Site. +
+
+
+
+
+
+
+
+
+
+
+
+ 7. CONTRIBUTION + LICENSE +
+
+
+
+
+
+
+
+ By posting your Contributions + to any part of the Site or making Contributions accessible to the Site by linking your account from + the Site to any of your social networking accounts, you automatically grant, and you represent and warrant + that you have the right to grant, to us an unrestricted, unlimited, irrevocable, perpetual, non-exclusive, + transferable, royalty-free, fully-paid, worldwide right, and license to host, use, copy, reproduce, + disclose, sell, resell, publish, broadcast, retitle, archive, store, cache, publicly perform, publicly + display, reformat, translate, transmit, excerpt (in whole or in part), and distribute such Contributions + (including, without limitation, your image and voice) for any purpose, commercial, advertising, or + otherwise, and to prepare derivative works of, or incorporate into other works, such Contributions, and + grant and authorize sublicenses of the foregoing. The use and distribution may occur in any media formats + and through any media channels. +
+
+
+
+
+
+
+ This license will apply to + any form, media, or technology now known or hereafter developed, and includes our use of your name, + company name, and franchise name, as applicable, and any of the trademarks, service marks, trade names, + logos, and personal and commercial images you provide. You waive all moral rights in your Contributions, + and you warrant that moral rights have not otherwise been asserted in your Contributions. +
+
+
+
+
+
+
+ We do not assert any + ownership over your Contributions. You retain full ownership of all of your Contributions and any + intellectual property rights or other proprietary rights associated with your Contributions. We are not + liable for any statements or representations in your Contributions provided by you in any area on the + Site. You are solely responsible for your Contributions to the Site and you expressly agree to exonerate + us from any and all responsibility and to refrain from any legal action against us regarding your + Contributions. +
+
+
+
+
+
+ We have the right, in our sole + and absolute discretion, (1) to edit, redact, or otherwise change any Contributions; (2) to re-categorize + any Contributions to place them in more appropriate locations on the Site; and (3) to pre-screen or delete + any Contributions at any time and for any reason, without notice. We have no obligation to monitor your + Contributions. +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+ 8. SOCIAL + MEDIA +
+
+
+
+
+ As + part of the functionality of the Site, you may link your account with online accounts you have with third-party + service providers (each such account, a “Third-Party Account”) by either: (1) providing your Third-Party Account + login information through the Site; or (2) allowing us to access your Third-Party Account, as is permitted under + the applicable terms and conditions that govern your use of each Third-Party Account. You represent and warrant + that you are entitled to disclose your Third-Party Account login information to us and/or grant us access to + your Third-Party Account, without breach by you of any of the terms and conditions that govern your use of the + applicable Third-Party Account, and without obligating us to pay any fees or making us subject to any usage + limitations imposed by the third-party service provider of the Third-Party Account. By granting us access to any + Third-Party Accounts, you understand that (1) we may access, make available, and store (if applicable) any + content that you have provided to and stored in your Third-Party Account (the “Social Network Content”) so that + it is available on and through the Site via your account, including without limitation any friend lists and (2) + we may submit to and receive from your Third-Party Account additional information to the extent you are notified + when you link your account with the Third-Party Account. Depending on the Third-Party Accounts you choose and + subject to the privacy settings that you have set in such Third-Party Accounts, personally identifiable + information that you post to your Third-Party Accounts may be available on and through your account on the Site. + Please note that if a Third-Party Account or associated service becomes unavailable or our access to such Third + Party Account is terminated by the third-party service provider, then Social Network Content may no longer be + available on and through the Site. You will have the ability to disable the connection between your account on + the Site and your Third-Party Accounts at any time. PLEASE NOTE THAT YOUR RELATIONSHIP WITH THE THIRD-PARTY + SERVICE PROVIDERS ASSOCIATED WITH YOUR THIRD-PARTY ACCOUNTS IS GOVERNED SOLELY BY YOUR AGREEMENT(S) WITH SUCH + THIRD-PARTY SERVICE PROVIDERS. We make no effort to review any Social Network Content for any purpose, including + but not limited to, for accuracy, legality, or non-infringement, and we are not responsible for any Social + Network Content. You acknowledge and agree that we may access your email address book associated with a + Third-Party Account and your contacts list stored on your mobile device or tablet computer solely for purposes + of identifying and informing you of those contacts who have also registered to use the Site. You can deactivate + the connection between the Site and your Third-Party Account by contacting us using the contact information + below or through your account settings (if applicable). We will attempt to delete any information stored on our + servers that was obtained through such Third-Party Account, except the username and profile picture that become + associated with your account. +
+
+
+
+
+
+
+
+
+ 9. SUBMISSIONS +
+
+
+
+
+ You + acknowledge and agree that any questions, comments, suggestions, ideas, feedback, or other information + regarding the Site ("Submissions") provided by you to us are non-confidential and shall become our sole + property. We shall own exclusive rights, including all intellectual property rights, and shall be entitled to + the unrestricted use and dissemination of these Submissions for any lawful purpose, commercial or otherwise, + without acknowledgment or compensation to you. You hereby waive all moral rights to any such Submissions, and + you hereby warrant that any such Submissions are original with you or that you have the right to submit such + Submissions. You agree there shall be no recourse against us for any alleged or actual infringement or + misappropriation of any proprietary right in your Submissions. +
+
+
+
+
+
+
+
+
+ 10. THIRD-PARTY + WEBSITE AND CONTENT +
+
+
+
+
+ The + Site may contain (or you may be sent via the Site) links to other websites ("Third-Party Websites") as well as + articles, photographs, text, graphics, pictures, designs, music, sound, video, information, applications, + software, and other content or items belonging to or originating from third parties ("Third-Party Content"). + Such Third-Party Websites and Third-Party Content are not investigated, monitored, or checked for accuracy, + appropriateness, or completeness by us, and we are not responsible for any Third-Party Websites accessed through + the Site or any Third-Party Content posted on, available through, or installed from the Site, including the + content, accuracy, offensiveness, opinions, reliability, privacy practices, or other policies of or contained in + the Third-Party Websites or the Third-Party Content. Inclusion of, linking to, or permitting the use or + installation of any Third-Party Websites or any Third-Party Content does not imply approval or endorsement + thereof by us. If you decide to leave the Site and access the Third-Party Websites or to use or install any + Third-Party Content, you do so at your own risk, and you should be aware these Terms of Use no longer govern. + You should review the applicable terms and policies, including privacy and data gathering practices, of any + website to which you navigate from the Site or relating to any applications you use or install from the Site. + Any purchases you make through Third-Party Websites will be through other websites and from other companies, and + we take no responsibility whatsoever in relation to such purchases which are exclusively between you and the + applicable third party. You agree and acknowledge that we do not endorse the products or services offered on + Third-Party Websites and you shall hold us harmless from any harm caused by your purchase of such products or + services. Additionally, you shall hold us harmless from any losses sustained by you or harm caused to you + relating to or resulting in any way from any Third-Party Content or any contact with Third-Party + Websites. +
+
+
+
+
+
+
+
+
+
+ +
+
+ 11. SITE + MANAGEMENT +
+
+
+
+
+
+
+ We + reserve the right, but not the obligation, to: (1) monitor the Site for violations of these Terms of Use; (2) + take appropriate legal action against anyone who, in our sole discretion, violates the law or these Terms of + Use, including without limitation, reporting such user to law enforcement authorities; (3) in our sole + discretion and without limitation, refuse, restrict access to, limit the availability of, or disable (to the + extent technologically feasible) any of your Contributions or any portion thereof; (4) in our sole discretion + and without limitation, notice, or liability, to remove from the Site or otherwise disable all files and + content that are excessive in size or are in any way burdensome to our systems; and (5) otherwise manage the + Site in a manner designed to protect our rights and property and to facilitate the proper functioning of the + Site. +
+
+
+
+
+
+
+
+
+
+ +
+
+ 12. PRIVACY + POLICY +
+
+
+
+
+ We + care about data privacy and security. Please review our Privacy Policy: https://insiders.vernite.dev/?path=/privacy-policyBy using the Site, you agree to be bound by our Privacy + Policy, which is incorporated into these Terms of Use. Please be advised the Site is hosted in Poland. If you access the + Site from any other region of the world with laws or other requirements governing personal data collection, + use, or disclosure that differ from applicable laws in Poland, then through your + continued use of the Site, you are transferring your data to Poland, and you agree to + have your data transferred to and processed in Poland. +
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+ 13. COPYRIGHT + INFRINGEMENTS +
+
+
+
+
+ We respect the intellectual property rights of others. If you believe that any + material available on or through the Site infringes upon any copyright you own or control, please immediately + notify us using the contact information provided below (a “Notification”). A copy of your Notification will be + sent to the person who posted or stored the material addressed in the Notification. Please be advised that + pursuant to applicable law you may be held liable for damages if you make material misrepresentations in a + Notification. Thus, if you are not sure that material located on or linked to by the Site infringes your + copyright, you should consider first contacting an attorney. +
+
+
+
+
+
+
+
+
+
+ 14. TERM + AND TERMINATION +
+
+
+
+
+
+
+ These Terms of Use + shall remain in full force and effect while you use the Site. WITHOUT LIMITING ANY OTHER PROVISION OF THESE + TERMS OF USE, WE RESERVE THE RIGHT TO, IN OUR SOLE DISCRETION AND WITHOUT NOTICE OR LIABILITY, DENY ACCESS TO + AND USE OF THE SITE (INCLUDING BLOCKING CERTAIN IP ADDRESSES), TO ANY PERSON FOR ANY REASON OR FOR NO REASON, + INCLUDING WITHOUT LIMITATION FOR BREACH OF ANY REPRESENTATION, WARRANTY, OR COVENANT CONTAINED IN THESE TERMS + OF USE OR OF ANY APPLICABLE LAW OR REGULATION. WE MAY TERMINATE YOUR USE OR PARTICIPATION IN THE SITE OR + DELETE YOUR ACCOUNT AND ANY CONTENT OR INFORMATION THAT YOU POSTED AT ANY TIME, WITHOUT WARNING, IN OUR + SOLE DISCRETION. +
+
+
+
+
+
+
+ If + we terminate or suspend your account for any reason, you are prohibited from registering and creating a new + account under your name, a fake or borrowed name, or the name of any third party, even if you may be acting on + behalf of the third party. In addition to terminating or suspending your account, we reserve the right to take + appropriate legal action, including without limitation pursuing civil, criminal, and injunctive + redress. +
+
+
+
+
+
+
+
+
+
+ 15. MODIFICATIONS + AND INTERRUPTIONS +
+
+
+
+
+
+
+ We + reserve the right to change, modify, or remove the contents of the Site at any time or for any reason at our + sole discretion without notice. However, we have no obligation to update any information on our Site. We also + reserve the right to modify or discontinue all or part of the Site without notice at any time. We will not be + liable to you or any third party for any modification, price change, suspension, or discontinuance of the + Site. +
+
+
+
+
+
+
+ We + cannot guarantee the Site will be available at all times. We may experience hardware, software, or other + problems or need to perform maintenance related to the Site, resulting in interruptions, delays, or errors. We + reserve the right to change, revise, update, suspend, discontinue, or otherwise modify the Site at any time or + for any reason without notice to you. You agree that we have no liability whatsoever for any loss, damage, or + inconvenience caused by your inability to access or use the Site during any downtime or discontinuance of the + Site. Nothing in these Terms of Use will be construed to obligate us to maintain and support the Site or to + supply any corrections, updates, or releases in connection therewith. +
+
+
+
+
+
+
+
+
+
+ 16. GOVERNING + LAW +
+
+
+
+
+
+ These conditions are governed by + and interpreted following the laws of Poland, and the use of + the United Nations Convention of Contracts for the International Sale of Goods is expressly excluded. If + your habitual residence is in the EU, and you are a consumer, you additionally possess the protection + provided to you by obligatory provisions of the law of your country of residence. Aleksandra Serba, Adrian + Antkowiak, Marcin Czerniak, Bartosz Wawrzyniak and yourself both agree to submit to the non-exclusive + jurisdiction of the courts of __________, which means that you may make a claim to defend your consumer + protection rights in regards to these Terms of Use in Poland, or in the + EU country in which you reside. +
+
+
+
+
+
+
+
+ 17. DISPUTE + RESOLUTION +
+
+
+
+
+
+
+
+ Informal Negotiations +
+
+
+
+
+
+
+ To expedite resolution and + control the cost of any dispute, controversy, or claim related to these Terms of Use (each "Dispute" and + collectively, the “Disputes”) brought by either you or us (individually, a “Party” and collectively, the + “Parties”), the Parties agree to first attempt to negotiate any Dispute (except those Disputes expressly + provided below) informally for at least thirty (30) days before initiating arbitration. Such informal + negotiations commence upon written notice from one Party to the other Party. +
+
+
+
+
+
+
+ Binding Arbitration +
+
+
+
+
+
+
+
+ Any dispute arising from the relationships + between the Parties to this contract shall be determined by one arbitrator who will be chosen in accordance + with the Arbitration and Internal Rules of the European Court of Arbitration being part of the European Centre + of Arbitration having its seat in Strasbourg, and which are in force at the time the application for + arbitration is filed, and of which adoption of this clause constitutes acceptance. The seat of arbitration + shall be Poznań, Poland. The language of the + proceedings shall be English. Applicable rules of substantive law shall be the law of + Poland. +
+
+
+
+
+
+ Restrictions +
+
+
+
+
+
+
+ The Parties agree that any + arbitration shall be limited to the Dispute between the Parties individually. To the full extent permitted by + law, (a) no arbitration shall be joined with any other proceeding; (b) there is no right or authority for any + Dispute to be arbitrated on a class-action basis or to utilize class action procedures; and (c) there is no + right or authority for any Dispute to be brought in a purported representative capacity on behalf of the + general public or any other persons. +
+
+
+
+
+
+
+ Exceptions to Informal Negotiations and + Arbitration +
+
+
+
+
+
+
+ The Parties agree that the + following Disputes are not subject to the above provisions concerning informal negotiations and binding + arbitration: (a) any Disputes seeking to enforce or protect, or concerning the validity of, any of the + intellectual property rights of a Party; (b) any Dispute related to, or arising from, allegations of theft, + piracy, invasion of privacy, or unauthorized use; and (c) any claim for injunctive relief. If this provision + is found to be illegal or unenforceable, then neither Party will elect to arbitrate any Dispute falling within + that portion of this provision found to be illegal or unenforceable and such Dispute shall be decided by a + court of competent jurisdiction within the courts listed for jurisdiction above, and the Parties agree to + submit to the personal jurisdiction of that court. +
+
+
+
+
+
+
+
+
+
+
+ 18. CORRECTIONS +
+
+
+
+
+
+
+ There + may be information on the Site that contains typographical errors, inaccuracies, or omissions, including + descriptions, pricing, availability, and various other information. We reserve the right to correct any errors, + inaccuracies, or omissions and to change or update the information on the Site at any time, without prior + notice. +
+
+
+
+
+
+
+
+
+
+ 19. DISCLAIMER +
+
+
+
+
+
+
+ THE + SITE IS PROVIDED ON AN AS-IS AND AS-AVAILABLE BASIS. YOU AGREE THAT YOUR USE OF THE SITE AND OUR SERVICES WILL + BE AT YOUR SOLE RISK. TO THE FULLEST EXTENT PERMITTED BY LAW, WE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, IN + CONNECTION WITH THE SITE AND YOUR USE THEREOF, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. WE MAKE NO WARRANTIES OR + REPRESENTATIONS ABOUT THE ACCURACY OR COMPLETENESS OF THE SITE’S CONTENT OR THE CONTENT OF ANY WEBSITES LINKED + TO THE SITE AND WE WILL ASSUME NO LIABILITY OR RESPONSIBILITY FOR ANY (1) ERRORS, MISTAKES, OR INACCURACIES OF + CONTENT AND MATERIALS, (2) PERSONAL INJURY OR PROPERTY DAMAGE, OF ANY NATURE WHATSOEVER, RESULTING FROM YOUR + ACCESS TO AND USE OF THE SITE, (3) ANY UNAUTHORIZED ACCESS TO OR USE OF OUR SECURE SERVERS AND/OR ANY AND ALL + PERSONAL INFORMATION AND/OR FINANCIAL INFORMATION STORED THEREIN, (4) ANY INTERRUPTION OR CESSATION OF + TRANSMISSION TO OR FROM THE SITE, (5) ANY BUGS, VIRUSES, TROJAN HORSES, OR THE LIKE WHICH MAY BE TRANSMITTED TO + OR THROUGH THE SITE BY ANY THIRD PARTY, AND/OR (6) ANY ERRORS OR OMISSIONS IN ANY CONTENT AND MATERIALS OR FOR + ANY LOSS OR DAMAGE OF ANY KIND INCURRED AS A RESULT OF THE USE OF ANY CONTENT POSTED, TRANSMITTED, OR OTHERWISE + MADE AVAILABLE VIA THE SITE. WE DO NOT WARRANT, ENDORSE, GUARANTEE, OR ASSUME RESPONSIBILITY FOR ANY PRODUCT OR + SERVICE ADVERTISED OR OFFERED BY A THIRD PARTY THROUGH THE SITE, ANY HYPERLINKED WEBSITE, OR ANY WEBSITE OR + MOBILE APPLICATION FEATURED IN ANY BANNER OR OTHER ADVERTISING, AND WE WILL NOT BE A PARTY TO OR IN ANY WAY BE + RESPONSIBLE FOR MONITORING ANY TRANSACTION BETWEEN YOU AND ANY THIRD-PARTY PROVIDERS OF PRODUCTS OR SERVICES. AS + WITH THE PURCHASE OF A PRODUCT OR SERVICE THROUGH ANY MEDIUM OR IN ANY ENVIRONMENT, YOU SHOULD USE YOUR BEST + JUDGMENT AND EXERCISE CAUTION WHERE APPROPRIATE. +
+
+
+
+
+
+
+
+
+
+ 20. LIMITATIONS + OF LIABILITY +
+
+
+
+
+
+
+ IN + NO EVENT WILL WE OR OUR DIRECTORS, EMPLOYEES, OR AGENTS BE LIABLE TO YOU OR ANY THIRD PARTY FOR ANY DIRECT, + INDIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL, OR PUNITIVE DAMAGES, INCLUDING LOST PROFIT, LOST + REVENUE, LOSS OF DATA, OR OTHER DAMAGES ARISING FROM YOUR USE OF THE SITE, EVEN IF WE HAVE BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGES. +
+
+
+
+
+
+
+
+
+
+ 21. INDEMNIFICATION +
+
+
+
+
+
+
+ You + agree to defend, indemnify, and hold us harmless, including our subsidiaries, affiliates, and all of our + respective officers, agents, partners, and employees, from and against any loss, damage, liability, claim, or + demand, including reasonable attorneys’ fees and expenses, made by any third party due to or arising out of: (1) + your Contributions; (2) use of the Site; (3) breach of these Terms of Use; (4) any breach of your representations and warranties set forth in these + Terms of Use; (5) your violation of the rights of a third party, + including but not limited to intellectual property rights; or (6) any + overt harmful act toward any other user of the Site with whom you connected via the Site. Notwithstanding the + foregoing, we reserve the right, at your expense, to assume the exclusive defense and control of any matter for + which you are required to indemnify us, and you agree to cooperate, at your expense, with our defense of such + claims. We will use reasonable efforts to notify you of any such claim, action, or proceeding which is subject + to this indemnification upon becoming aware of it. +
+
+
+
+
+
+
+
+
+
+ 22. USER + DATA +
+
+
+
+
+
+
+ We + will maintain certain data that you transmit to the Site for the purpose of managing the performance of the + Site, as well as data relating to your use of the Site. Although we perform regular routine backups of data, you + are solely responsible for all data that you transmit or that relates to any activity you have undertaken using + the Site. You agree that we shall have no liability to you for any loss or corruption of any such data, and you + hereby waive any right of action against us arising from any such loss or corruption of such data. +
+
+
+
+
+
+
+
+
+
+ 23. ELECTRONIC + COMMUNICATIONS, TRANSACTIONS, AND SIGNATURES +
+
+
+
+
+
+
+ Visiting + the Site, sending us emails, and completing online forms constitute electronic communications. You consent to + receive electronic communications, and you agree that all agreements, notices, disclosures, and other + communications we provide to you electronically, via email and on the Site, satisfy any legal requirement that + such communication be in writing. YOU HEREBY AGREE TO THE USE OF ELECTRONIC SIGNATURES, CONTRACTS, ORDERS, AND + OTHER RECORDS, AND TO ELECTRONIC DELIVERY OF NOTICES, POLICIES, AND RECORDS OF TRANSACTIONS INITIATED OR + COMPLETED BY US OR VIA THE SITE. You hereby waive any rights or requirements under any statutes, regulations, + rules, ordinances, or other laws in any jurisdiction which require an original signature or delivery or + retention of non-electronic records, or to payments or the granting of credits by any means other than + electronic means. +
+
+
+
+
+
+
+
+
+ 24. CALIFORNIA + USERS AND RESIDENTS +
+
+
+
+
+
+
+ If + any complaint with us is not satisfactorily resolved, you can contact the Complaint Assistance Unit of the + Division of Consumer Services of the California Department of Consumer Affairs in writing at 1625 North Market + Blvd., Suite N 112, Sacramento, California 95834 or by telephone at (800) 952-5210 or (916) 445-1254. +
+
+
+
+
+
+
+
+
+ 25. MISCELLANEOUS +
+
+
+
+
+
+
+ These + Terms of Use and any policies or operating rules posted by us on the Site or in respect to the Site constitute + the entire agreement and understanding between you and us. Our failure to exercise or enforce any right or + provision of these Terms of Use shall not operate as a waiver of such right or provision. These Terms of Use + operate to the fullest extent permissible by law. We may assign any or all of our rights and obligations to + others at any time. We shall not be responsible or liable for any loss, damage, delay, or failure to act caused + by any cause beyond our reasonable control. If any provision or part of a provision of these Terms of Use is + determined to be unlawful, void, or unenforceable, that provision or part of the provision is deemed severable + from these Terms of Use and does not affect the validity and enforceability of any remaining provisions. There + is no joint venture, partnership, employment or agency relationship created between you and us as a result of + these Terms of Use or use of the Site. You agree that these Terms of Use will not be construed against us by + virtue of having drafted them. You hereby waive any and all defenses you may have based on the electronic form + of these Terms of Use and the lack of signing by the parties hereto to execute these Terms of Use. +
+
+
+
+
+
+
+
+
+
+ 26. CONTACT + US +
+
+
+
+
+
+
+ In + order to resolve a complaint regarding the Site or to receive further information regarding use of the Site, + please contact us at: +
+
+
+
+
+
+
+ Aleksandra + Serba, Adrian Antkowiak, Marcin Czerniak, Bartosz Wawrzyniak +
+
+
+
+ __________ +
+
+
+ Poland +
+
+
+
+
+ contact.vernite@gmail.com +
+
+ +
+
diff --git a/src/app/_main/pages/terms-and-conditions/terms-and-conditions.page.scss b/src/app/_main/pages/terms-and-conditions/terms-and-conditions.page.scss new file mode 100644 index 000000000..d409f7137 --- /dev/null +++ b/src/app/_main/pages/terms-and-conditions/terms-and-conditions.page.scss @@ -0,0 +1,4 @@ +:host { + display: block; + padding: 3rem; +} diff --git a/src/app/_main/pages/terms-and-conditions/terms-and-conditions.page.ts b/src/app/_main/pages/terms-and-conditions/terms-and-conditions.page.ts new file mode 100644 index 000000000..7e2404491 --- /dev/null +++ b/src/app/_main/pages/terms-and-conditions/terms-and-conditions.page.ts @@ -0,0 +1,25 @@ +import { Component, OnInit } from '@angular/core'; +import { NavigationEnd, Router } from '@angular/router'; + +@Component({ + selector: 'app-terms-and-conditions', + templateUrl: './terms-and-conditions.page.html', + styleUrls: ['./terms-and-conditions.page.scss'], +}) +export class TermsAndConditionsPage implements OnInit { + constructor(private router: Router) {} + + ngOnInit() { + this.router.events.subscribe((event) => { + if (event instanceof NavigationEnd) { + const tree = this.router.parseUrl(this.router.url); + if (tree.fragment) { + const element = document.querySelector('#' + tree.fragment); + if (element) { + element.scrollIntoView(); + } + } + } + }); + } +} diff --git a/src/app/_main/pipes/date-time-by-preferences/date-time-by-preferences.pipe.ts b/src/app/_main/pipes/date-time-by-preferences/date-time-by-preferences.pipe.ts new file mode 100644 index 000000000..a210b43e6 --- /dev/null +++ b/src/app/_main/pipes/date-time-by-preferences/date-time-by-preferences.pipe.ts @@ -0,0 +1,43 @@ +import { PipeTransform } from '@angular/core'; +import dayjs from 'dayjs'; +import { Pipe } from '@angular/core'; +import { UserService } from '@auth/services/user/user.service'; +import { EMPTY, map } from 'rxjs'; + +/** + * DateTime by preferences pipe - display date with time by user preferences + */ +@Pipe({ + name: 'dateTimeByPreferences', +}) +export class DateTimeByPreferencesPipe implements PipeTransform { + constructor(private userService: UserService) {} + + /** + * Display date and time by user preferences + * @param value unix timestamp in seconds or milliseconds + * @param format type of input format + * @returns + */ + transform(value: any, format: 'milliseconds' | 'seconds' = 'milliseconds'): any { + if (value) { + if (format === 'milliseconds') { + return this.userService + .getMyself() + .pipe( + map(({ dateFormat, timeFormat }) => dayjs(value).format(`${dateFormat} ${timeFormat}`)), + ); + } else if (format === 'seconds') { + return this.userService + .getMyself() + .pipe( + map(({ dateFormat, timeFormat }) => + dayjs(value * 1000).format(`${dateFormat} ${timeFormat}`), + ), + ); + } + } else { + return EMPTY; + } + } +} diff --git a/src/app/_main/services/router-extensions/router-extensions.service.ts b/src/app/_main/services/router-extensions/router-extensions.service.ts index 53e5c0c06..232bc9279 100644 --- a/src/app/_main/services/router-extensions/router-extensions.service.ts +++ b/src/app/_main/services/router-extensions/router-extensions.service.ts @@ -33,7 +33,7 @@ export class RouterExtensionsService { * Get language from url * @returns language from url */ - private getLanguageFromUrl() { + public getLanguageFromUrl() { const languagePredicate = location.pathname.split('/')[1]; if (!languagePredicate) return null; @@ -51,4 +51,14 @@ export class RouterExtensionsService { private getBaseHref() { return document.getElementsByTagName('base')[0].href; } + + public reloadWithLanguage(language: string) { + if (this.getLanguageFromUrl() === language) return; + if (this.getLanguageFromUrl() === null) location.reload(); + else { + const splittedLocation = location.pathname.split('/'); + splittedLocation[1] = language; + location.pathname = splittedLocation.join('/'); + } + } } diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts index 08cd3adbc..f24a55908 100644 --- a/src/app/app.routing.ts +++ b/src/app/app.routing.ts @@ -3,6 +3,8 @@ import { RouterModule, Routes } from '@angular/router'; import { LoggedInUsersGuard } from './auth/guard/logged-in-users.guard'; import { LandingPageComponent } from './landing-page/landing-page/landing-page.component'; import { MainViewComponent } from './_main/components/main-view/main-view.component'; +import { TermsAndConditionsPage } from './_main/pages/terms-and-conditions/terms-and-conditions.page'; +import { PrivacyPolicyPage } from './_main/pages/privacy-policy/privacy-policy.page'; const routes: Routes = [ { @@ -10,34 +12,60 @@ const routes: Routes = [ loadChildren: () => import('./auth/auth.module').then((m) => m.AuthModule), }, { - path: 'landing-page', - // TODO: Move this to lazy loading module + path: 'terms-and-conditions', + component: TermsAndConditionsPage, + }, + { + path: 'privacy-policy', + component: PrivacyPolicyPage, + }, + { + path: 'about', + component: LandingPageComponent, + }, + { + path: 'changelog', + component: LandingPageComponent, + }, + { + path: 'docs', component: LandingPageComponent, }, { path: '', - component: MainViewComponent, - canActivate: [LoggedInUsersGuard], children: [ { - path: 'email', - loadChildren: () => import('./emails/emails.module').then((m) => m.EmailsModule), - }, - { - path: 'calendar', - loadChildren: () => import('./calendar/calendar.module').then((m) => m.CalendarModule), - }, - { - path: 'messages', - loadChildren: () => import('./messages/messages.module').then((m) => m.MessagesModule), - }, - { - path: 'meetings', - loadChildren: () => import('./meetings/meetings.module').then((m) => m.MeetingsModule), + path: '', + pathMatch: 'full', + component: LandingPageComponent, }, { path: '', - loadChildren: () => import('./dashboard/dashboard.module').then((m) => m.DashboardModule), + component: MainViewComponent, + canActivate: [LoggedInUsersGuard], + children: [ + { + path: 'email', + loadChildren: () => import('./emails/emails.module').then((m) => m.EmailsModule), + }, + { + path: 'calendar', + loadChildren: () => import('./calendar/calendar.module').then((m) => m.CalendarModule), + }, + { + path: 'messages', + loadChildren: () => import('./messages/messages.module').then((m) => m.MessagesModule), + }, + { + path: 'meetings', + loadChildren: () => import('./meetings/meetings.module').then((m) => m.MeetingsModule), + }, + { + path: '', + loadChildren: () => + import('./dashboard/dashboard.module').then((m) => m.DashboardModule), + }, + ], }, ], }, diff --git a/src/app/auth/auth.module.ts b/src/app/auth/auth.module.ts index a3cd17afa..4e9ae0e33 100644 --- a/src/app/auth/auth.module.ts +++ b/src/app/auth/auth.module.ts @@ -7,6 +7,9 @@ import { ChangePasswordPage } from './pages/change-password/change-password.page import { DeleteAccountPage } from './pages/delete-account/delete-account.page'; import { ForgotPasswordPage } from './pages/forgot-password/forgot-password.page'; import { LoginPage } from './pages/login/login.page'; +import { RegisterInProgressPage } from './pages/register-in-progress/register-in-progress.page'; +import { RegisterTokenExpiredPage } from './pages/register-token-expired/register-token-expired.page'; +import { RegisterTokenSuccessPage } from './pages/register-token-success/register-token-success.page'; import { RegisterPage } from './pages/register/register.page'; import { RestoreAccountPage } from './pages/restore-account/restore-account.page'; @@ -19,6 +22,9 @@ import { RestoreAccountPage } from './pages/restore-account/restore-account.page ChangePasswordPage, RestoreAccountPage, DeleteAccountPage, + RegisterInProgressPage, + RegisterTokenExpiredPage, + RegisterTokenSuccessPage, ], }) export class AuthModule {} diff --git a/src/app/auth/auth.routing.ts b/src/app/auth/auth.routing.ts index b1d749756..63daeb6e4 100644 --- a/src/app/auth/auth.routing.ts +++ b/src/app/auth/auth.routing.ts @@ -4,6 +4,9 @@ import { ChangePasswordPage } from './pages/change-password/change-password.page import { DeleteAccountPage } from './pages/delete-account/delete-account.page'; import { ForgotPasswordPage } from './pages/forgot-password/forgot-password.page'; import { LoginPage } from './pages/login/login.page'; +import { RegisterInProgressPage } from './pages/register-in-progress/register-in-progress.page'; +import { RegisterTokenExpiredPage } from './pages/register-token-expired/register-token-expired.page'; +import { RegisterTokenSuccessPage } from './pages/register-token-success/register-token-success.page'; import { RegisterPage } from './pages/register/register.page'; import { RestoreAccountPage } from './pages/restore-account/restore-account.page'; @@ -19,10 +22,6 @@ const routes: Routes = [ path: 'logout', component: LoginPage, }, - { - path: 'register', - component: RegisterPage, - }, { path: 'password-reset', component: ForgotPasswordPage, @@ -39,6 +38,28 @@ const routes: Routes = [ path: 'delete-account', component: DeleteAccountPage, }, + { + path: 'register', + children: [ + { + path: 'in-progress', + component: RegisterInProgressPage, + }, + { + path: 'token-success', + component: RegisterTokenSuccessPage, + }, + { + path: 'token-expired', + component: RegisterTokenExpiredPage, + }, + { + path: '', + pathMatch: 'full', + component: RegisterPage, + }, + ], + }, ]; /** diff --git a/src/app/auth/guard/logged-in-users.guard.ts b/src/app/auth/guard/logged-in-users.guard.ts index d8a5d5198..c612e1307 100644 --- a/src/app/auth/guard/logged-in-users.guard.ts +++ b/src/app/auth/guard/logged-in-users.guard.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { CanActivate, Router } from '@angular/router'; +import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router'; import { AuthService } from '@auth/services/auth/auth.service'; /** @@ -13,7 +13,17 @@ export class LoggedInUsersGuard implements CanActivate { * Check if user is logged in * @returns true if user is logged in, false otherwise */ - canActivate() { + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { + console.log(state.url); + if ( + state.url == '/' || + state.url == '/about' || + state.url == '/docs' || + state.url == '/changelog' + ) { + return true; + } + if (this.authService.isLocallyLoggedIn()) { return true; } else { diff --git a/src/app/auth/interfaces/user.interface.ts b/src/app/auth/interfaces/user.interface.ts index f6ab29859..a2cd2697d 100644 --- a/src/app/auth/interfaces/user.interface.ts +++ b/src/app/auth/interfaces/user.interface.ts @@ -45,13 +45,20 @@ export interface User extends JSONParsable { */ dateFormat: string; + /** + * User language. + */ + language: string; + /** * Time format used by user. + * @Note This feature is not implemented in API yet. */ timeFormat: string; /** * User first day of week. + * @Note This feature is not implemented in API yet. */ firstDayOfWeek: number; diff --git a/src/app/auth/pages/forgot-password/forgot-password.page.html b/src/app/auth/pages/forgot-password/forgot-password.page.html index 6585800fa..6ce02586e 100644 --- a/src/app/auth/pages/forgot-password/forgot-password.page.html +++ b/src/app/auth/pages/forgot-password/forgot-password.page.html @@ -4,7 +4,7 @@
diff --git a/src/app/auth/pages/login/login.page.ts b/src/app/auth/pages/login/login.page.ts index 704502863..00ad26740 100644 --- a/src/app/auth/pages/login/login.page.ts +++ b/src/app/auth/pages/login/login.page.ts @@ -45,7 +45,7 @@ export class LoginPage implements OnInit { if (!isLoggedIn) return; localStorage.setItem('logged', 'true'); - this.router.navigate(['/']); + this.router.navigate(['/dashboard']); }); } @@ -75,7 +75,7 @@ export class LoginPage implements OnInit { if (response.deleted) { this.router.navigate(['/auth/restore-account']); } else { - this.router.navigate(['/']); + this.router.navigate(['/dashboard']); } }); } @@ -89,7 +89,7 @@ export class LoginPage implements OnInit { switch (error.status) { case 403: this.error = $localize`User is already logged`; - this.router.navigate(['/']); + this.router.navigate(['/dashboard']); break; case 404: this.error = $localize`Wrong username or password`; diff --git a/src/app/auth/pages/register-in-progress/register-in-progress.page.html b/src/app/auth/pages/register-in-progress/register-in-progress.page.html new file mode 100644 index 000000000..87e3d762c --- /dev/null +++ b/src/app/auth/pages/register-in-progress/register-in-progress.page.html @@ -0,0 +1,23 @@ +
+
+
+ +
+
+

Your registration was successful!

+

Please check your email for a confirmation link and click it within the next 30 minutes to complete the registration process.

+
+ +
+
+
+
diff --git a/src/app/auth/pages/register-in-progress/register-in-progress.page.scss b/src/app/auth/pages/register-in-progress/register-in-progress.page.scss new file mode 100644 index 000000000..5bdf554e3 --- /dev/null +++ b/src/app/auth/pages/register-in-progress/register-in-progress.page.scss @@ -0,0 +1,127 @@ +.logo { + position: absolute; + width: calc(100% - 80px); + height: 64px; + align-self: flex-start; + margin-top: 20px; + background-image: url('../../../../assets/metadata/logo_with_name.svg'); + background-position: 0 50%; + background-repeat: no-repeat; + background-size: contain; + cursor: pointer; +} + +.main { + display: flex; + width: 100%; + min-height: 100vh; + align-items: center; + justify-content: center; + background-color: var(--color-neutral-800); + + .box { + display: flex; + width: 100%; + height: 100%; + + .form-side { + position: relative; + display: flex; + width: 100%; + height: 100%; + flex-direction: column; + align-items: center; + padding: 0 2rem; + background-color: var(--color-gray-800); + } + } +} + +@screen sm { + .main { + .box { + width: 500px; + height: 770px; + } + } +} + +@screen md { + .main { + .box { + width: 500px; + height: 770px; + } + } +} + +@screen lg { + .main { + .box { + width: 950px; + height: 770px; + } + } +} + +@screen xl { + .main { + .box { + width: 1240px; + height: 770px; + } + } +} + +.navigate-button { + position: relative; + display: flex; + align-items: center; + cursor: pointer; + gap: 0.5rem; + + &:hover { + span { + color: var(--color-link-hover); + text-decoration: underline; + } + + app-icon { + color: var(--color-link-hover); + } + } + + app-icon { + display: inline-block; + display: flex; + align-items: center; + justify-content: center; + color: var(--color-link); + } + + span { + color: var(--color-link); + transition: color 0.1s ease; + } +} + +.container { + display: flex; + width: 100%; + max-width: 600px; + flex-direction: column; + flex-grow: 1; + align-items: center; + justify-content: center; + text-align: center; + + .text-xl { + margin-top: 2rem; + } +} + +.buttons { + display: flex; + margin-top: 2rem; + gap: 2rem; +} diff --git a/src/app/auth/pages/register-in-progress/register-in-progress.page.ts b/src/app/auth/pages/register-in-progress/register-in-progress.page.ts new file mode 100644 index 000000000..8a5f85d45 --- /dev/null +++ b/src/app/auth/pages/register-in-progress/register-in-progress.page.ts @@ -0,0 +1,19 @@ +import { Component } from '@angular/core'; +import { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons'; + +/** + * Register in progress page component + */ +@Component({ + selector: 'app-register-in-progress-page', + templateUrl: './register-in-progress.page.html', + styleUrls: ['./register-in-progress.page.scss'], +}) +export class RegisterInProgressPage { + constructor() {} + + /** @ignore */ + faChevronLeft = faChevronLeft; + + faChevronRight = faChevronRight; +} diff --git a/src/app/auth/pages/register-token-expired/register-token-expired.page.html b/src/app/auth/pages/register-token-expired/register-token-expired.page.html new file mode 100644 index 000000000..0ea3aa3ae --- /dev/null +++ b/src/app/auth/pages/register-token-expired/register-token-expired.page.html @@ -0,0 +1,23 @@ +
+
+
+ +
+
+

Your link has expired!

+

Sorry, your email confirmation link has expired. Please request a new confirmation link to complete the registration process.

+
+ +
+
+
+
diff --git a/src/app/auth/pages/register-token-expired/register-token-expired.page.scss b/src/app/auth/pages/register-token-expired/register-token-expired.page.scss new file mode 100644 index 000000000..5bdf554e3 --- /dev/null +++ b/src/app/auth/pages/register-token-expired/register-token-expired.page.scss @@ -0,0 +1,127 @@ +.logo { + position: absolute; + width: calc(100% - 80px); + height: 64px; + align-self: flex-start; + margin-top: 20px; + background-image: url('../../../../assets/metadata/logo_with_name.svg'); + background-position: 0 50%; + background-repeat: no-repeat; + background-size: contain; + cursor: pointer; +} + +.main { + display: flex; + width: 100%; + min-height: 100vh; + align-items: center; + justify-content: center; + background-color: var(--color-neutral-800); + + .box { + display: flex; + width: 100%; + height: 100%; + + .form-side { + position: relative; + display: flex; + width: 100%; + height: 100%; + flex-direction: column; + align-items: center; + padding: 0 2rem; + background-color: var(--color-gray-800); + } + } +} + +@screen sm { + .main { + .box { + width: 500px; + height: 770px; + } + } +} + +@screen md { + .main { + .box { + width: 500px; + height: 770px; + } + } +} + +@screen lg { + .main { + .box { + width: 950px; + height: 770px; + } + } +} + +@screen xl { + .main { + .box { + width: 1240px; + height: 770px; + } + } +} + +.navigate-button { + position: relative; + display: flex; + align-items: center; + cursor: pointer; + gap: 0.5rem; + + &:hover { + span { + color: var(--color-link-hover); + text-decoration: underline; + } + + app-icon { + color: var(--color-link-hover); + } + } + + app-icon { + display: inline-block; + display: flex; + align-items: center; + justify-content: center; + color: var(--color-link); + } + + span { + color: var(--color-link); + transition: color 0.1s ease; + } +} + +.container { + display: flex; + width: 100%; + max-width: 600px; + flex-direction: column; + flex-grow: 1; + align-items: center; + justify-content: center; + text-align: center; + + .text-xl { + margin-top: 2rem; + } +} + +.buttons { + display: flex; + margin-top: 2rem; + gap: 2rem; +} diff --git a/src/app/auth/pages/register-token-expired/register-token-expired.page.ts b/src/app/auth/pages/register-token-expired/register-token-expired.page.ts new file mode 100644 index 000000000..2d65e92a3 --- /dev/null +++ b/src/app/auth/pages/register-token-expired/register-token-expired.page.ts @@ -0,0 +1,19 @@ +import { Component } from '@angular/core'; +import { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons'; + +/** + * Register in progress page component + */ +@Component({ + selector: 'app-register-token-expired-page', + templateUrl: './register-token-expired.page.html', + styleUrls: ['./register-token-expired.page.scss'], +}) +export class RegisterTokenExpiredPage { + constructor() {} + + /** @ignore */ + faChevronLeft = faChevronLeft; + + faChevronRight = faChevronRight; +} diff --git a/src/app/auth/pages/register-token-success/register-token-success.page.html b/src/app/auth/pages/register-token-success/register-token-success.page.html new file mode 100644 index 000000000..293aab5b9 --- /dev/null +++ b/src/app/auth/pages/register-token-success/register-token-success.page.html @@ -0,0 +1,23 @@ +
+
+
+ +
+
+

Your registration was successful!

+

Your email address has been confirmed! Thank you for completing the registration process.

+
+ +
+
+
+
diff --git a/src/app/auth/pages/register-token-success/register-token-success.page.scss b/src/app/auth/pages/register-token-success/register-token-success.page.scss new file mode 100644 index 000000000..5bdf554e3 --- /dev/null +++ b/src/app/auth/pages/register-token-success/register-token-success.page.scss @@ -0,0 +1,127 @@ +.logo { + position: absolute; + width: calc(100% - 80px); + height: 64px; + align-self: flex-start; + margin-top: 20px; + background-image: url('../../../../assets/metadata/logo_with_name.svg'); + background-position: 0 50%; + background-repeat: no-repeat; + background-size: contain; + cursor: pointer; +} + +.main { + display: flex; + width: 100%; + min-height: 100vh; + align-items: center; + justify-content: center; + background-color: var(--color-neutral-800); + + .box { + display: flex; + width: 100%; + height: 100%; + + .form-side { + position: relative; + display: flex; + width: 100%; + height: 100%; + flex-direction: column; + align-items: center; + padding: 0 2rem; + background-color: var(--color-gray-800); + } + } +} + +@screen sm { + .main { + .box { + width: 500px; + height: 770px; + } + } +} + +@screen md { + .main { + .box { + width: 500px; + height: 770px; + } + } +} + +@screen lg { + .main { + .box { + width: 950px; + height: 770px; + } + } +} + +@screen xl { + .main { + .box { + width: 1240px; + height: 770px; + } + } +} + +.navigate-button { + position: relative; + display: flex; + align-items: center; + cursor: pointer; + gap: 0.5rem; + + &:hover { + span { + color: var(--color-link-hover); + text-decoration: underline; + } + + app-icon { + color: var(--color-link-hover); + } + } + + app-icon { + display: inline-block; + display: flex; + align-items: center; + justify-content: center; + color: var(--color-link); + } + + span { + color: var(--color-link); + transition: color 0.1s ease; + } +} + +.container { + display: flex; + width: 100%; + max-width: 600px; + flex-direction: column; + flex-grow: 1; + align-items: center; + justify-content: center; + text-align: center; + + .text-xl { + margin-top: 2rem; + } +} + +.buttons { + display: flex; + margin-top: 2rem; + gap: 2rem; +} diff --git a/src/app/auth/pages/register-token-success/register-token-success.page.ts b/src/app/auth/pages/register-token-success/register-token-success.page.ts new file mode 100644 index 000000000..c4dfb887e --- /dev/null +++ b/src/app/auth/pages/register-token-success/register-token-success.page.ts @@ -0,0 +1,19 @@ +import { Component } from '@angular/core'; +import { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons'; + +/** + * Register in progress page component + */ +@Component({ + selector: 'app-register-token-success-page', + templateUrl: './register-token-success.page.html', + styleUrls: ['./register-token-success.page.scss'], +}) +export class RegisterTokenSuccessPage { + constructor() {} + + /** @ignore */ + faChevronLeft = faChevronLeft; + + faChevronRight = faChevronRight; +} diff --git a/src/app/auth/pages/register/register.page.html b/src/app/auth/pages/register/register.page.html index a691b2575..edf1746eb 100644 --- a/src/app/auth/pages/register/register.page.html +++ b/src/app/auth/pages/register/register.page.html @@ -25,7 +25,10 @@

Register

diff --git a/src/app/auth/pages/register/register.page.ts b/src/app/auth/pages/register/register.page.ts index ec031c513..baada4c0f 100644 --- a/src/app/auth/pages/register/register.page.ts +++ b/src/app/auth/pages/register/register.page.ts @@ -119,7 +119,7 @@ export class RegisterPage { }), ) .subscribe(() => { - this.router.navigate(['/']); + this.router.navigate(['/register/in-progress']); }); } } diff --git a/src/app/auth/services/user/user.service.ts b/src/app/auth/services/user/user.service.ts index cd606558d..9bcfcdfce 100644 --- a/src/app/auth/services/user/user.service.ts +++ b/src/app/auth/services/user/user.service.ts @@ -5,23 +5,161 @@ import { Cache } from '@main/decorators/cache/cache.decorator'; import { ErrorCodes, Errors } from '@main/interfaces/http-error.interface'; import { ApiService } from '@main/services/api/api.service'; import { BaseService } from '@main/services/base/base.service'; -import { Observable, map } from 'rxjs'; +import { Observable, map, switchMap, tap } from 'rxjs'; import { AuthService } from '../auth/auth.service'; import { unixTimestamp } from '../../../_main/interfaces/date.interface'; +import { Service } from '../../../_main/decorators/service/service.decorator'; +import { RouterExtensionsService } from '../../../_main/services/router-extensions/router-extensions.service'; +import { mergeWith } from 'lodash-es'; +import * as dayjs from 'dayjs'; /** * User service */ +@Service() @Injectable({ providedIn: 'root', }) export class UserService extends BaseService> { protected errorCodes: ErrorCodes = {}; + private dayjs_locales = [ + 'af', + 'ar', + 'ar-dz', + 'ar-kw', + 'ar-ly', + 'ar-ma', + 'ar-sa', + 'ar-tn', + 'az', + 'be', + 'bg', + 'bm', + 'bn', + 'bo', + 'br', + 'bs', + 'ca', + 'cs', + 'cv', + 'cy', + 'da', + 'de', + 'de-at', + 'de-ch', + 'dv', + 'el', + 'en', + 'en-au', + 'en-ca', + 'en-gb', + 'en-ie', + 'en-il', + 'en-nz', + 'en-SG', + 'eo', + 'es', + 'es-do', + 'es-us', + 'et', + 'eu', + 'fa', + 'fi', + 'fo', + 'fr', + 'fr-ca', + 'fr-ch', + 'fy', + 'ga', + 'gd', + 'gl', + 'gom-latn', + 'gu', + 'he', + 'hi', + 'hr', + 'hu', + 'hy-am', + 'id', + 'is', + 'it', + 'it-ch', + 'ja', + 'jv', + 'ka', + 'kk', + 'km', + 'kn', + 'ko', + 'ku', + 'ky', + 'lb', + 'lo', + 'lt', + 'lv', + 'me', + 'mi', + 'mk', + 'ml', + 'mn', + 'mr', + 'ms', + 'ms-my', + 'mt', + 'my', + 'nb', + 'ne', + 'nl', + 'nl-be', + 'nn', + 'oc-lnc', + 'pa-in', + 'pl', + 'pt', + 'pt-br', + 'ro', + 'ru', + 'sd', + 'se', + 'si', + 'sk', + 'sl', + 'sq', + 'sr', + 'sr-cyrl', + 'ss', + 'sv', + 'sw', + 'ta', + 'te', + 'tet', + 'tg', + 'th', + 'tl-ph', + 'tlh', + 'tr', + 'tzl', + 'tzm', + 'tzm-latn', + 'ug-cn', + 'uk', + 'ur', + 'uz', + 'uz-latn', + 'vi', + 'x-pseudo', + 'yo', + 'zh-cn', + 'zh-hk', + 'zh-tw', + ]; + constructor( private injector: Injector, private apiService: ApiService, private authService: AuthService, + private routerExtensionsService: RouterExtensionsService, ) { super(injector); } @@ -32,19 +170,34 @@ export class UserService extends BaseService> { */ public getUserDefaultPreferences() { return { + language: navigator.language || this.routerExtensionsService.getLanguageFromUrl(), dateFormat: 'DD.MM.YYYY', timeFormat: 'HH:mm', firstDayOfWeek: 1, }; } + public mergeUserWithDefaultPreferences(user: User): User { + return mergeWith( + {} as any, + this.getUserDefaultPreferences() as any, + user as any, + (a: any, b: any) => { + if (b === null || b === undefined) { + return a; + } + return b; + }, + ) as any as User; + } + /** * Update user * @param user user * @returns updated user */ public update(user: Partial): Observable { - return this.apiService.put(`/auth/edit`, { body: user }); + return this.apiService.put(`/auth/edit`, { body: user }).pipe(tap(() => this.loadLocale())); } /** @@ -55,7 +208,7 @@ export class UserService extends BaseService> { public getMyself(): Observable { return this.apiService .get(`/auth/me`) - .pipe(map((user) => Object.assign({}, this.getUserDefaultPreferences(), user))); + .pipe(map((user: User) => this.mergeUserWithDefaultPreferences(user))); } /** @@ -67,6 +220,14 @@ export class UserService extends BaseService> { return this.getMyself().pipe(map((user: User) => user.dateFormat)); } + /** + * Get user's time format + */ + @Cache({ interval: Number.POSITIVE_INFINITY }) + public getTimeFormat(): Observable { + return this.getMyself().pipe(map((user: User) => user.timeFormat)); + } + /** * Clear cache */ @@ -95,4 +256,38 @@ export class UserService extends BaseService> { }) .pipe(this.validate({})); } + + public loadLocale(): void { + this.getMyself().subscribe((user: User) => { + if ( + this.routerExtensionsService.getLanguageFromUrl() && + user.language !== this.routerExtensionsService.getLanguageFromUrl() + ) { + this.routerExtensionsService.reloadWithLanguage(user.language); + return; + } + + let locale = 'en'; + + if (this.dayjs_locales.includes(user.language.toLowerCase())) { + locale = user.language.toLowerCase(); + } else if (this.dayjs_locales.includes(user.language.toLowerCase().split('-')[0])) { + locale = user.language.toLowerCase().split('-')[0]; + } + + dayjs.updateLocale(locale, { + weekStart: user.firstDayOfWeek, + }); + dayjs.locale(locale); + + localStorage.setItem( + 'locale', + JSON.stringify({ + weekStart: user.firstDayOfWeek, + }), + ); + + localStorage.setItem('userLocale', locale); + }); + } } diff --git a/src/app/calendar/components/calendar-grid/calendar-grid.component.html b/src/app/calendar/components/calendar-grid/calendar-grid.component.html index 959b64aca..a2671bf33 100644 --- a/src/app/calendar/components/calendar-grid/calendar-grid.component.html +++ b/src/app/calendar/components/calendar-grid/calendar-grid.component.html @@ -1,6 +1,6 @@
{{ weekdayShort }}
+ [class.current-month]="day.date.isBetween(firstDay, lastDay, 'day', '[]')">

{{ day.date | dayjsFormat:'D' }}

diff --git a/src/app/calendar/components/calendar-grid/calendar-grid.component.ts b/src/app/calendar/components/calendar-grid/calendar-grid.component.ts index 5f7ce08e1..22fc0876d 100644 --- a/src/app/calendar/components/calendar-grid/calendar-grid.component.ts +++ b/src/app/calendar/components/calendar-grid/calendar-grid.component.ts @@ -3,6 +3,7 @@ import { EventType } from '@calendar/enums/event-type.enum'; import { Event } from '@calendar/interfaces/event.interface'; import { Task } from '@tasks/interfaces/task.interface'; import * as dayjs from 'dayjs'; +import { weekdaysShort } from '@main/libs/localization/weekdays.localization.lib'; /** * Calendar grid component to display calendar @@ -39,7 +40,7 @@ export class CalendarGridComponent implements OnChanges { public tasksByDate = new Map(); /** List of weekdays */ - public weekdaysShort = dayjs.weekdaysShort(); + public weekdaysShort = weekdaysShort(); ngOnChanges(changes: SimpleChanges) { if (changes['date'] && !changes['date'].currentValue.isSame(changes['date'].previousValue)) { diff --git a/src/app/dashboard/dashboard.routing.ts b/src/app/dashboard/dashboard.routing.ts index c3b6b16be..a982cc7ed 100644 --- a/src/app/dashboard/dashboard.routing.ts +++ b/src/app/dashboard/dashboard.routing.ts @@ -14,11 +14,6 @@ import { ProjectPage } from './pages/project/project.page'; * Dashboard routes list */ const routes: Routes = [ - { - path: '', - pathMatch: 'full', - component: WorkspacesListPage, - }, { path: 'settings', loadChildren: () => import('../settings/settings.module').then((m) => m.SettingsModule), diff --git a/src/app/dashboard/pages/create-workspace/create-workspace.page.ts b/src/app/dashboard/pages/create-workspace/create-workspace.page.ts index ae4c0ac89..122630a62 100644 --- a/src/app/dashboard/pages/create-workspace/create-workspace.page.ts +++ b/src/app/dashboard/pages/create-workspace/create-workspace.page.ts @@ -47,7 +47,7 @@ export class CreateWorkspacePage { if (this.form.invalid) return; this.createSubscription = this.workspaceService.create(this.form.value).subscribe(() => { - this.router.navigate(['/']).then(() => { + this.router.navigate(['/workspaces']).then(() => { window.location.reload(); }); }); diff --git a/src/app/dashboard/pages/edit-workspace/edit-workspace.page.ts b/src/app/dashboard/pages/edit-workspace/edit-workspace.page.ts index 5d312dd9b..1418be79e 100644 --- a/src/app/dashboard/pages/edit-workspace/edit-workspace.page.ts +++ b/src/app/dashboard/pages/edit-workspace/edit-workspace.page.ts @@ -73,7 +73,7 @@ export class EditWorkspacePage { if (this.form.invalid) return; this.updateSubscription = this.workspaceService.update(this.form.value).subscribe(() => { - this.router.navigate(['/']).then(() => { + this.router.navigate(['/workspaces']).then(() => { window.location.reload(); }); }); diff --git a/src/app/messages/components/message-group/message-group.component.html b/src/app/messages/components/message-group/message-group.component.html index b9d1092dd..4b77c429a 100644 --- a/src/app/messages/components/message-group/message-group.component.html +++ b/src/app/messages/components/message-group/message-group.component.html @@ -7,7 +7,7 @@ {{ author?.displayName || author?.name }}
- {{ messages[0].timestamp | dateByPreferences:'seconds' | async }} + {{ messages[0].timestamp | dateTimeByPreferences:'seconds' | async }}
diff --git a/src/app/messages/components/message/message.component.html b/src/app/messages/components/message/message.component.html index 31f35ba2e..4125c7a34 100644 --- a/src/app/messages/components/message/message.component.html +++ b/src/app/messages/components/message/message.component.html @@ -1,2 +1,2 @@ -
diff --git a/src/app/releases/dialog/release/release.dialog.html b/src/app/releases/dialog/release/release.dialog.html index e01c9c139..61ee7f6bb 100644 --- a/src/app/releases/dialog/release/release.dialog.html +++ b/src/app/releases/dialog/release/release.dialog.html @@ -12,7 +12,7 @@

C - + diff --git a/src/app/releases/pages/releases-list/releases-list.page.html b/src/app/releases/pages/releases-list/releases-list.page.html index 57eb35ae7..25ccc9f58 100644 --- a/src/app/releases/pages/releases-list/releases-list.page.html +++ b/src/app/releases/pages/releases-list/releases-list.page.html @@ -10,7 +10,8 @@

Releases

Name - {{ row.name }} + {{ row.name }} + @@ -23,14 +24,15 @@

Releases

Progress - + Release date - {{row.deadline | dateByPreferences | async}} + {{row.deadline | dateTimeByPreferences | async}} diff --git a/src/app/settings/pages/settings-localization/settings-localization.page.html b/src/app/settings/pages/settings-localization/settings-localization.page.html index f20218be9..f98a23ef8 100644 --- a/src/app/settings/pages/settings-localization/settings-localization.page.html +++ b/src/app/settings/pages/settings-localization/settings-localization.page.html @@ -16,6 +16,12 @@

Localization

{{ timeFormat.example }} + + + Sunday + Monday + +
Save settings diff --git a/src/app/settings/pages/settings-localization/settings-localization.page.ts b/src/app/settings/pages/settings-localization/settings-localization.page.ts index b752d95bf..ae887d129 100644 --- a/src/app/settings/pages/settings-localization/settings-localization.page.ts +++ b/src/app/settings/pages/settings-localization/settings-localization.page.ts @@ -20,6 +20,7 @@ export class SettingsLocalizationPage implements OnInit { language: new FormControl('', requiredValidator()), dateFormat: new FormControl(''), timeFormat: new FormControl(''), + firstDayOfWeek: new FormControl(0), }); /** diff --git a/src/app/tasks/components/board-task/board-task.component.html b/src/app/tasks/components/board-task/board-task.component.html index 24c116f39..a7f9c3463 100644 --- a/src/app/tasks/components/board-task/board-task.component.html +++ b/src/app/tasks/components/board-task/board-task.component.html @@ -8,7 +8,7 @@
Due date
-
{{ task.deadline | dateByPreferences | async }}
+
{{ task.deadline | dateTimeByPreferences | async }}

diff --git a/src/app/tasks/components/task-list/task-list.component.html b/src/app/tasks/components/task-list/task-list.component.html index 565490337..095afedcb 100644 --- a/src/app/tasks/components/task-list/task-list.component.html +++ b/src/app/tasks/components/task-list/task-list.component.html @@ -1,22 +1,26 @@
- - -
-
Title
-
Status
-
Assignee
-
Time tracking
-
Deadline
-
Story points
-
- -
-
- -
- + +
+
Title
+
Status
+
Assignee
+
Time tracking
+
Deadline
+
Story points
+
+
- +
+ + +
+ + +
+
diff --git a/src/app/tasks/components/task-list/task-list.component.scss b/src/app/tasks/components/task-list/task-list.component.scss index 326a70d67..64fe6b5a5 100644 --- a/src/app/tasks/components/task-list/task-list.component.scss +++ b/src/app/tasks/components/task-list/task-list.component.scss @@ -8,3 +8,40 @@ z-index: 2; background-color: var(--color-secondary-700); } + +.show-more { + position: relative; + display: flex; + overflow: hidden; + width: 100%; + align-items: center; + justify-content: center; + padding: 1rem; + margin-top: 1rem; + border-radius: var(--border-radius); + color: var(--color-text); + cursor: pointer; + gap: 0.5rem; + + span { + z-index: 2; + } + + &:hover { + &::before { + opacity: 0.3; + } + } + + &::before { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: black; + content: ''; + opacity: 0.2; + transition: opacity 0.2s ease-in-out; + } +} diff --git a/src/app/tasks/components/task-list/task-list.component.ts b/src/app/tasks/components/task-list/task-list.component.ts index b52023d51..35275f81d 100644 --- a/src/app/tasks/components/task-list/task-list.component.ts +++ b/src/app/tasks/components/task-list/task-list.component.ts @@ -1,8 +1,9 @@ -import { Component, Input, ViewChild } from '@angular/core'; +import { Component, Input, ViewChild, OnChanges, SimpleChanges, OnInit } from '@angular/core'; import { Status } from '@tasks/interfaces/status.interface'; import { Task } from '@tasks/interfaces/task.interface'; import { ProjectMember } from '../../../dashboard/interfaces/project-member.interface'; import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling'; +import { faPlus } from '@fortawesome/free-solid-svg-icons'; /** * Component to display list of tasks @@ -12,7 +13,7 @@ import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling'; templateUrl: './task-list.component.html', styleUrls: ['./task-list.component.scss'], }) -export class TaskListComponent { +export class TaskListComponent implements OnInit, OnChanges { /** Tasks to display */ @Input() tasks: Task[] = []; @@ -25,21 +26,31 @@ export class TaskListComponent { /** List of project statuses */ @Input() statusList: Status[] = []; - @ViewChild(CdkVirtualScrollViewport, { static: false }) - public viewPort!: CdkVirtualScrollViewport; + /** @ignore */ + faPlus = faPlus; + + public visibleTasks: Task[] = []; + public currentLimit: number = 50; constructor() {} - public get inverseOfTranslation(): string { - if (!this.viewPort || !this.viewPort['_renderedContentOffset']) { - return '-0px'; + ngOnInit() { + this.visibleTasks = this.tasks.slice(0, this.currentLimit); + } + + ngOnChanges(changes: SimpleChanges) { + if (changes['tasks']) { + this.visibleTasks = this.tasks.slice(0, this.currentLimit); } - let offset = this.viewPort['_renderedContentOffset']; - return `-${offset}px`; } /** Track by function for tasks */ trackByTask(index: number, task: Task) { return task.id; } + + increaseLimit() { + this.currentLimit += 50; + this.visibleTasks = this.tasks.slice(0, this.currentLimit); + } } diff --git a/src/app/tasks/components/task-row/task-row.component.html b/src/app/tasks/components/task-row/task-row.component.html index d42ff556b..6e37e1050 100644 --- a/src/app/tasks/components/task-row/task-row.component.html +++ b/src/app/tasks/components/task-row/task-row.component.html @@ -43,7 +43,7 @@
-
{{ task.deadline | dateByPreferences | async }}
+
{{ task.deadline | dateTimeByPreferences | async }}
diff --git a/src/app/tasks/dialogs/sprint/sprint.dialog.html b/src/app/tasks/dialogs/sprint/sprint.dialog.html index 4cca92437..d3fc98335 100644 --- a/src/app/tasks/dialogs/sprint/sprint.dialog.html +++ b/src/app/tasks/dialogs/sprint/sprint.dialog.html @@ -12,7 +12,7 @@

Cr - + diff --git a/src/app/tasks/guards/active-sprint-exist.guard.ts b/src/app/tasks/guards/active-sprint-exist.guard.ts index 538766f99..a063ac9a2 100644 --- a/src/app/tasks/guards/active-sprint-exist.guard.ts +++ b/src/app/tasks/guards/active-sprint-exist.guard.ts @@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'; import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router'; import { Observable, map } from 'rxjs'; import { SprintService } from '../services/sprint.service'; +import { HttpParams } from '@angular/common/http'; @Injectable({ providedIn: 'root', @@ -11,7 +12,7 @@ export class ActiveSprintExistGuard implements CanActivate { canActivate( route: ActivatedRouteSnapshot, - _: RouterStateSnapshot, + state: RouterStateSnapshot, ): Observable | Promise | boolean { const projectId = Number(route.paramMap.get('projectId')); diff --git a/src/app/tasks/pages/backlog/backlog.page.html b/src/app/tasks/pages/backlog/backlog.page.html index ea7db386c..8076cc575 100644 --- a/src/app/tasks/pages/backlog/backlog.page.html +++ b/src/app/tasks/pages/backlog/backlog.page.html @@ -1,7 +1,7 @@ -
+

{{sprint.name}}

Close sprint @@ -31,7 +31,7 @@

-
+

{{sprint.name}}

@@ -63,7 +63,7 @@

-
+

Backlog

diff --git a/src/app/tasks/pages/task/task.page.html b/src/app/tasks/pages/task/task.page.html index 08f2be6bd..b2659e3a9 100644 --- a/src/app/tasks/pages/task/task.page.html +++ b/src/app/tasks/pages/task/task.page.html @@ -106,8 +106,8 @@

Dates

- {{ task.createdAt | dateByPreferences | async }} - {{ task.lastUpdated | dateByPreferences | async }} + {{ task.createdAt | dateTimeByPreferences | async }} + {{ task.lastUpdated | dateTimeByPreferences | async }}
diff --git a/src/app/tasks/tasks.routing.ts b/src/app/tasks/tasks.routing.ts index 5860db510..209d17a3f 100644 --- a/src/app/tasks/tasks.routing.ts +++ b/src/app/tasks/tasks.routing.ts @@ -13,7 +13,8 @@ const routes: Routes = [ { path: '', pathMatch: 'full', - redirectTo: 'sprint', + canActivate: [ActiveSprintExistGuard], + children: [], }, { path: 'about', @@ -29,8 +30,7 @@ const routes: Routes = [ { path: '', pathMatch: 'full', - canActivate: [ActiveSprintExistGuard], - children: [], + component: SprintPage, }, { path: ':sprintId', diff --git a/src/index.html b/src/index.html index 27b36562a..0a2549326 100644 --- a/src/index.html +++ b/src/index.html @@ -19,7 +19,6 @@ - Vernite diff --git a/src/main.ts b/src/main.ts index 314763bf9..8ad2aa750 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,6 +3,7 @@ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; +import * as dayjs from 'dayjs'; if (environment.production) { enableProdMode(); @@ -21,3 +22,11 @@ platformBrowserDynamic() (window as any)['ngRef'] = ref; }) .catch((err) => console.error(err)); + +const persistentLocale = localStorage.getItem('locale'); +const userLocale = localStorage.getItem('userLocale'); + +if (persistentLocale && userLocale) { + dayjs.updateLocale(userLocale, JSON.parse(persistentLocale)); + dayjs.locale(userLocale); +} diff --git a/src/polyfills.ts b/src/polyfills.ts index 17e371d30..f378a1313 100644 --- a/src/polyfills.ts +++ b/src/polyfills.ts @@ -63,14 +63,19 @@ import objectSupport from 'dayjs/plugin/objectSupport'; import formatParser from 'dayjs/plugin/customParseFormat'; import isToday from 'dayjs/plugin/isToday'; import isBetween from 'dayjs/plugin/isBetween'; +import updateLocale from 'dayjs/plugin/updateLocale'; import { environment } from './environments/environment'; +import 'dayjs/locale/en'; +import 'dayjs/locale/pl'; + dayjs.extend(utc); dayjs.extend(localeData); dayjs.extend(objectSupport); dayjs.extend(formatParser); dayjs.extend(isToday); dayjs.extend(isBetween); +dayjs.extend(updateLocale); if (!environment.production) { (window as any).dayjs = dayjs;