Version 3 #40
|
@ -1,78 +0,0 @@
|
||||||
<template>
|
|
||||||
<form class="container">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12 col-sm-6 col-md-4 col-lg-3">
|
|
||||||
<continent-list v-model="criteria.continentId" topLabel="Any" @update:modelValue="updateContinent" />
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-sm-6 col-md-4 col-lg-3">
|
|
||||||
<div class="form-floating">
|
|
||||||
<input type="text" id="region" class="form-control form-control-sm" maxlength="1000"
|
|
||||||
placeholder="(free-form text)" :value="criteria.region"
|
|
||||||
@input="updateValue('region', $event.target.value)">
|
|
||||||
<label for="region">Region</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-text">(free-form text)</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-sm-6 col-offset-md-2 col-lg-3 col-offset-lg-0">
|
|
||||||
<label class="jjj-label">Seeking Remote Work?</label><br>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input type="radio" id="remoteNull" class="form-check-input" name="remoteWork"
|
|
||||||
:checked="criteria.remoteWork === ''" @click="updateValue('remoteWork', '')">
|
|
||||||
<label class="form-check-label" for="remoteNull">No Selection</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input type="radio" id="remoteYes" class="form-check-input" name="remoteWork"
|
|
||||||
:checked="criteria.remoteWork === 'yes'" @click="updateValue('remoteWork', 'yes')">
|
|
||||||
<label class="form-check-label" for="remoteYes">Yes</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check form-check-inline">
|
|
||||||
<input type="radio" id="remoteNo" class="form-check-input" name="remoteWork"
|
|
||||||
:checked="criteria.remoteWork === 'no'" @click="updateValue('remoteWork', 'no')">
|
|
||||||
<label class="form-check-label" for="remoteNo">No</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-sm-6 col-lg-3">
|
|
||||||
<div class="form-floating">
|
|
||||||
<input type="text" id="skillSearch" class="form-control form-control-sm" maxlength="1000"
|
|
||||||
placeholder="(free-form text)" :value="criteria.skill"
|
|
||||||
@input="updateValue('skill', $event.target.value)">
|
|
||||||
<label for="skillSearch">Skill</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-text">(free-form text)</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<br>
|
|
||||||
<button class="btn btn-outline-primary" type="submit" @click.prevent="$emit('search')">Search</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref } from "vue"
|
|
||||||
import { PublicSearch } from "@/api"
|
|
||||||
import ContinentList from "../ContinentList.vue"
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
modelValue: PublicSearch
|
|
||||||
}>()
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: "search") : void
|
|
||||||
(e: "update:modelValue", value : PublicSearch) : void
|
|
||||||
}>()
|
|
||||||
|
|
||||||
/** The initial search criteria passed; this is what we'll update and emit when data changes */
|
|
||||||
const criteria = ref({ ...props.modelValue })
|
|
||||||
|
|
||||||
/** Emit a value update */
|
|
||||||
const updateValue = (key : string, value : string) => {
|
|
||||||
criteria.value = { ...criteria.value, [key]: value }
|
|
||||||
emit("update:modelValue", criteria.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Update the continent ID */
|
|
||||||
const updateContinent = (c : string) => updateValue("continentId", c)
|
|
||||||
</script>
|
|
|
@ -36,18 +36,6 @@ const routes: Array<RouteRecordRaw> = [
|
||||||
component: () => import(/* webpackChunkName: "help" */ "../views/HowItWorks.vue"),
|
component: () => import(/* webpackChunkName: "help" */ "../views/HowItWorks.vue"),
|
||||||
meta: { auth: false, title: "How It Works" }
|
meta: { auth: false, title: "How It Works" }
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "/privacy-policy",
|
|
||||||
name: "PrivacyPolicy",
|
|
||||||
component: () => import(/* webpackChunkName: "legal" */ "../views/PrivacyPolicy.vue"),
|
|
||||||
meta: { auth: false, title: "Privacy Policy" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/terms-of-service",
|
|
||||||
name: "TermsOfService",
|
|
||||||
component: () => import(/* webpackChunkName: "legal" */ "../views/TermsOfService.vue"),
|
|
||||||
meta: { auth: false, title: "Terms of Service" }
|
|
||||||
},
|
|
||||||
// Citizen URLs
|
// Citizen URLs
|
||||||
{
|
{
|
||||||
path: "/citizen/account",
|
path: "/citizen/account",
|
||||||
|
@ -86,13 +74,6 @@ const routes: Array<RouteRecordRaw> = [
|
||||||
component: () => import(/* webpackChunkName: "joblist" */ "../views/listing/MyListings.vue"),
|
component: () => import(/* webpackChunkName: "joblist" */ "../views/listing/MyListings.vue"),
|
||||||
meta: { auth: true, title: "My Job Listings" }
|
meta: { auth: true, title: "My Job Listings" }
|
||||||
},
|
},
|
||||||
// Profile URLs
|
|
||||||
{
|
|
||||||
path: "/profile/seeking",
|
|
||||||
name: "PublicSearchProfiles",
|
|
||||||
component: () => import(/* webpackChunkName: "seeking" */ "../views/profile/Seeking.vue"),
|
|
||||||
meta: { auth: false, title: "People Seeking Work" }
|
|
||||||
},
|
|
||||||
// "So Long" URLs
|
// "So Long" URLs
|
||||||
{
|
{
|
||||||
path: "/so-long/options",
|
path: "/so-long/options",
|
||||||
|
|
|
@ -1,430 +0,0 @@
|
||||||
<template>
|
|
||||||
<article>
|
|
||||||
<h3>Privacy Policy</h3>
|
|
||||||
<p class="fst-italic">(as of August 30<sup>th</sup>, 2021)</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
{{name}} (“we,” “our,” or “us”) is committed to protecting your privacy. This
|
|
||||||
Privacy Policy explains how your personal information is collected, used, and disclosed by {{name}}.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
This Privacy Policy applies to our website, and its associated subdomains (collectively, our
|
|
||||||
“Service”) alongside our application, {{name}}. By accessing or using our Service, you signify that
|
|
||||||
you have read, understood, and agree to our collection, storage, use, and disclosure of your personal information
|
|
||||||
as described in this Privacy Policy and our Terms of Service.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>Definitions and key terms</h4>
|
|
||||||
<p>
|
|
||||||
To help explain things as clearly as possible in this Privacy Policy, every time any of these terms are referenced,
|
|
||||||
are strictly defined as:
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Cookie: small amount of data generated by a website and saved by your web browser. It is used to identify your
|
|
||||||
browser, provide analytics, remember information about you such as your language preference or login
|
|
||||||
information.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Company: when this policy mentions “Company,” “we,” “us,” or
|
|
||||||
“our,” it refers to {{name}}, that is responsible for your information under this Privacy Policy.
|
|
||||||
</li>
|
|
||||||
<li>Country: where {{name}} or the owners/founders of {{name}} are based, in this case is US.</li>
|
|
||||||
<li>
|
|
||||||
Customer: refers to the company, organization or person that signs up to use the {{name}} Service to manage the
|
|
||||||
relationships with your consumers or service users.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Device: any internet connected device such as a phone, tablet, computer or any other device that can be used to
|
|
||||||
visit {{name}} and use the services.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
IP address: Every device connected to the Internet is assigned a number known as an Internet protocol (IP)
|
|
||||||
address. These numbers are usually assigned in geographic blocks. An IP address can often be used to identify
|
|
||||||
the location from which a device is connecting to the Internet.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Personnel: refers to those individuals who are employed by {{name}} or are under contract to perform a service
|
|
||||||
on behalf of one of the parties.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Personal Data: any information that directly, indirectly, or in connection with other information — including a
|
|
||||||
personal identification number — allows for the identification or identifiability of a natural person.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Service: refers to the service provided by {{name}} as described in the relative terms (if available) and on
|
|
||||||
this platform.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Third-party service: refers to advertisers, contest sponsors, promotional and marketing partners, and others who
|
|
||||||
provide our content or whose products or services we think may interest you.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Website: {{name}}’s site, which can be accessed via this URL:
|
|
||||||
<router-link to="/">https://noagendacareers.com/</router-link>
|
|
||||||
</li>
|
|
||||||
<li>You: a person or entity that is registered with {{name}} to use the Services.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h4>What Information Do We Collect?</h4>
|
|
||||||
<p>We collect information from you when you visit our website, register on our site, or fill out a form.</p>
|
|
||||||
<ul>
|
|
||||||
<li>Name / Username</li>
|
|
||||||
<li>Coarse Geographic Location</li>
|
|
||||||
<li>Employment History</li>
|
|
||||||
<li>Job Listing Information</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h4>How Do We Use The Information We Collect?</h4>
|
|
||||||
<p>Any of the information we collect from you may be used in one of the following ways:</p>
|
|
||||||
<ul>
|
|
||||||
<li>To personalize your experience (your information helps us to better respond to your individual needs)</li>
|
|
||||||
<li>
|
|
||||||
To improve our website (we continually strive to improve our website offerings based on the information and
|
|
||||||
feedback we receive from you)
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
To improve customer service (your information helps us to more effectively respond to your customer service
|
|
||||||
requests and support needs)
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h4>When does {{name}} use end user information from third parties?</h4>
|
|
||||||
<p>{{name}} will collect End User Data necessary to provide the {{name}} services to our customers.</p>
|
|
||||||
<p>
|
|
||||||
End users may voluntarily provide us with information they have made available on social media websites. If you
|
|
||||||
provide us with any such information, we may collect publicly available information from the social media websites
|
|
||||||
you have indicated. You can control how much of your information social media websites make public by visiting
|
|
||||||
these websites and changing your privacy settings.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>When does {{name}} use customer information from third parties?</h4>
|
|
||||||
<p>We do not utilize third party information apart from the end-user data described above.</p>
|
|
||||||
|
|
||||||
<h4>Do we share the information we collect with third parties?</h4>
|
|
||||||
<p>
|
|
||||||
We may disclose personal and non-personal information about you to government or law enforcement officials or
|
|
||||||
private parties as we, in our sole discretion, believe necessary or appropriate in order to respond to claims,
|
|
||||||
legal process (including subpoenas), to protect our rights and interests or those of a third party, the safety of
|
|
||||||
the public or any person, to prevent or stop any illegal, unethical, or legally actionable activity, or to
|
|
||||||
otherwise comply with applicable court orders, laws, rules and regulations.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>Where and when is information collected from customers and end users?</h4>
|
|
||||||
<p>
|
|
||||||
{{name}} will collect personal information that you submit to us. We may also receive personal information about you
|
|
||||||
from third parties as described above.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>How Do We Use Your E-mail Address?</h4>
|
|
||||||
<p>
|
|
||||||
{{name}} uses your e-mail address to identify you, along with your password, as an authorized user of this site.
|
|
||||||
E-mail addresses are verified via a time-sensitive link, and may also be used to send password reset authorization
|
|
||||||
codes. We do not display this e-mail address to users. If you choose to add an e-mail address as a contact type,
|
|
||||||
that e-mail address will be visible to other authorized users.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>How Long Do We Keep Your Information?</h4>
|
|
||||||
<p>
|
|
||||||
We keep your information only so long as we need it to provide {{name}} to you and fulfill the purposes described
|
|
||||||
in this policy. When we no longer need to use your information and there is no need for us to keep it to comply
|
|
||||||
with our legal or regulatory obligations, we’ll either remove it from our systems or depersonalize it so that we
|
|
||||||
can’t identify you.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>How Do We Protect Your Information?</h4>
|
|
||||||
<p>
|
|
||||||
We implement a variety of security measures to maintain the safety of your personal information when you enter,
|
|
||||||
submit, or access your personal information. We mandate the use of a secure server. We cannot, however, ensure or
|
|
||||||
warrant the absolute security of any information you transmit to {{name}} or guarantee that your information on
|
|
||||||
the Service may not be accessed, disclosed, altered, or destroyed by a breach of any of our physical, technical,
|
|
||||||
or managerial safeguards.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>Could my information be transferred to other countries?</h4>
|
|
||||||
<p>
|
|
||||||
{{name}} is hosted in the US. Information collected via our website may be viewed and hosted anywhere in the
|
|
||||||
world, including countries that may not have laws of general applicability regulating the use and transfer of
|
|
||||||
such data. To the fullest extent allowed by applicable law, by using any of the above, you voluntarily consent to
|
|
||||||
the trans-border transfer and hosting of such information.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>Is the information collected through the {{name}} Service secure?</h4>
|
|
||||||
<p>
|
|
||||||
We take precautions to protect the security of your information. We have physical, electronic, and managerial
|
|
||||||
procedures to help safeguard, prevent unauthorized access, maintain data security, and correctly use your
|
|
||||||
information. However, neither people nor security systems are foolproof, including encryption systems. In
|
|
||||||
addition, people can commit intentional crimes, make mistakes, or fail to follow policies. Therefore, while we
|
|
||||||
use reasonable efforts to protect your personal information, we cannot guarantee its absolute security. If
|
|
||||||
applicable law imposes any non-disclaimable duty to protect your personal information, you agree that intentional
|
|
||||||
misconduct will be the standards used to measure our compliance with that duty.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>Can I update or correct my information?</h4>
|
|
||||||
<p>
|
|
||||||
The rights you have to request updates or corrections to the information {{name}} collects depend on your
|
|
||||||
relationship with {{name}}.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Customers have the right to request the restriction of certain uses and disclosures of personally identifiable
|
|
||||||
information as follows. You can contact us in order to (1) update or correct your personally identifiable
|
|
||||||
information, or (3) delete the personally identifiable information maintained about you on our systems (subject to
|
|
||||||
the following paragraph), by cancelling your account. Such updates, corrections, changes and deletions will have
|
|
||||||
no effect on other information that we maintain in accordance with this Privacy Policy prior to such update,
|
|
||||||
correction, change, or deletion. You are responsible for maintaining the secrecy of your unique password and
|
|
||||||
account information at all times.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{{name}} also provides ways for users to modify or remove the information we have collected from them from the
|
|
||||||
application; these actions will have the same effect as contacting us to modify or remove data.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
You should be aware that it is not technologically possible to remove each and every record of the information you
|
|
||||||
have provided to us from our system. The need to back up our systems to protect information from inadvertent loss
|
|
||||||
means that a copy of your information may exist in a non-erasable form that will be difficult or impossible for us
|
|
||||||
to locate. Promptly after receiving your request, all personal information stored in databases we actively use,
|
|
||||||
and other readily searchable media will be updated, corrected, changed, or deleted, as appropriate, as soon as and
|
|
||||||
to the extent reasonably and technically practicable.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
If you are an end user and wish to update, delete, or receive any information we have about you, you may do so by
|
|
||||||
contacting the organization of which you are a customer.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>Governing Law</h4>
|
|
||||||
<p>
|
|
||||||
This Privacy Policy is governed by the laws of US without regard to its conflict of laws provision. You consent to
|
|
||||||
the exclusive jurisdiction of the courts in connection with any action or dispute arising between the parties
|
|
||||||
under or in connection with this Privacy Policy except for those individuals who may have rights to make claims
|
|
||||||
under Privacy Shield, or the Swiss-US framework.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The laws of US, excluding its conflicts of law rules, shall govern this Agreement and your use of the website.
|
|
||||||
Your use of the website may also be subject to other local, state, national, or international laws.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
By using {{name}} or contacting us directly, you signify your acceptance of this Privacy Policy. If you do not
|
|
||||||
agree to this Privacy Policy, you should not engage with our website, or use our services. Continued use of the
|
|
||||||
website, direct engagement with us, or following the posting of changes to this Privacy Policy that do not
|
|
||||||
significantly affect the use or disclosure of your personal information will mean that you accept those changes.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>Your Consent</h4>
|
|
||||||
<p>
|
|
||||||
We’ve updated our Privacy Policy to provide you with complete transparency into what is being set when you
|
|
||||||
visit our site and how it’s being used. By using our website, registering an account, or making a purchase,
|
|
||||||
you hereby consent to our Privacy Policy and agree to its terms.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>Links to Other Websites</h4>
|
|
||||||
<p>
|
|
||||||
This Privacy Policy applies only to the Services. The Services may contain links to other websites not operated or
|
|
||||||
controlled by {{name}}. We are not responsible for the content, accuracy or opinions expressed in such websites,
|
|
||||||
and such websites are not investigated, monitored or checked for accuracy or completeness by us. Please remember
|
|
||||||
that when you use a link to go from the Services to another website, our Privacy Policy is no longer in effect.
|
|
||||||
Your browsing and interaction on any other website, including those that have a link on our platform, is subject
|
|
||||||
to that website’s own rules and policies. Such third parties may use their own cookies or other methods to collect
|
|
||||||
information about you.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>Cookies</h4>
|
|
||||||
<p>{{name}} does not use Cookies.</p>
|
|
||||||
|
|
||||||
<h4>Kids’ Privacy</h4>
|
|
||||||
<p>
|
|
||||||
We do not address anyone under the age of 13. We do not knowingly collect personally identifiable information from
|
|
||||||
anyone under the age of 13. If You are a parent or guardian and You are aware that Your child has provided Us with
|
|
||||||
Personal Data, please contact Us. If We become aware that We have collected Personal Data from anyone under the
|
|
||||||
age of 13 without verification of parental consent, We take steps to remove that information from Our servers.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>Changes To Our Privacy Policy</h4>
|
|
||||||
<p>
|
|
||||||
We may change our Service and policies, and we may need to make changes to this Privacy Policy so that they
|
|
||||||
accurately reflect our Service and policies. Unless otherwise required by law, we will notify you (for example,
|
|
||||||
through our Service) before we make changes to this Privacy Policy and give you an opportunity to review them
|
|
||||||
before they go into effect. Then, if you continue to use the Service, you will be bound by the updated Privacy
|
|
||||||
Policy. If you do not want to agree to this or any updated Privacy Policy, you can delete your account.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>Third-Party Services</h4>
|
|
||||||
<p>
|
|
||||||
We may display, include or make available third-party content (including data, information, applications and other
|
|
||||||
products services) or provide links to third-party websites or services (“Third-Party Services”).
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
You acknowledge and agree that {{name}} shall not be responsible for any Third-Party Services, including their
|
|
||||||
accuracy, completeness, timeliness, validity, copyright compliance, legality, decency, quality or any other aspect
|
|
||||||
thereof. {{name}} does not assume and shall not have any liability or responsibility to you or any other person or
|
|
||||||
entity for any Third-Party Services.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Third-Party Services and links thereto are provided solely as a convenience to you and you access and use them
|
|
||||||
entirely at your own risk and subject to such third parties’ terms and conditions.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>Tracking Technologies</h4>
|
|
||||||
<p>
|
|
||||||
{{name}} does not use any tracking technologies. When a user signs in, a token is issued; that token is stored in
|
|
||||||
the browser’s memory, and the Service uses it on each request for data. If the page is refreshed or the
|
|
||||||
browser window/tab is closed, this token disappears, and a new one must be generated before the application can be
|
|
||||||
used again.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>Information about General Data Protection Regulation (GDPR)</h4>
|
|
||||||
<p>
|
|
||||||
We may be collecting and using information from you if you are from the European Economic Area (EEA), and in this
|
|
||||||
section of our Privacy Policy we are going to explain exactly how and why is this data collected, and how we
|
|
||||||
maintain this data under protection from being replicated or used in the wrong way.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h5>What is GDPR?</h5>
|
|
||||||
<p>
|
|
||||||
GDPR is an EU-wide privacy and data protection law that regulates how EU residents’ data is protected by
|
|
||||||
companies and enhances the control the EU residents have, over their personal data.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The GDPR is relevant to any globally operating company and not just the EU-based businesses and EU residents. Our
|
|
||||||
customers’ data is important irrespective of where they are located, which is why we have implemented GDPR
|
|
||||||
controls as our baseline standard for all our operations worldwide.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h5>What is personal data?</h5>
|
|
||||||
<p>
|
|
||||||
Any data that relates to an identifiable or identified individual. GDPR covers a broad spectrum of information
|
|
||||||
that could be used on its own, or in combination with other pieces of information, to identify a person. Personal
|
|
||||||
data extends beyond a person’s name or email address. Some examples include financial information, political
|
|
||||||
opinions, genetic data, biometric data, IP addresses, physical address, sexual orientation, and ethnicity.
|
|
||||||
</p>
|
|
||||||
<p>The Data Protection Principles include requirements such as:</p>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Personal data collected must be processed in a fair, legal, and transparent way and should only be used in a way
|
|
||||||
that a person would reasonably expect.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Personal data should only be collected to fulfil a specific purpose and it should only be used for that purpose.
|
|
||||||
Organizations must specify why they need the personal data when they collect it.
|
|
||||||
</li>
|
|
||||||
<li>Personal data should be held no longer than necessary to fulfil its purpose.</li>
|
|
||||||
<li>
|
|
||||||
People covered by the GDPR have the right to access their own personal data. They can also request a copy of
|
|
||||||
their data, and that their data be updated, deleted, restricted, or moved to another organization.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h5>Why is GDPR important?</h5>
|
|
||||||
<p>
|
|
||||||
GDPR adds some new requirements regarding how companies should protect individuals’ personal data that they
|
|
||||||
collect and process. It also raises the stakes for compliance by increasing enforcement and imposing greater fines
|
|
||||||
for breach. Beyond these facts, it’s simply the right thing to do. At {{name}} we strongly believe that your
|
|
||||||
data privacy is very important and we already have solid security and privacy practices in place that go beyond
|
|
||||||
the requirements of this regulation.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h5>Individual Data Subject’s Rights - Data Access, Portability, and Deletion</h5>
|
|
||||||
<p>
|
|
||||||
We are committed to helping our customers meet the data subject rights requirements of GDPR. {{name}} processes or
|
|
||||||
stores all personal data in fully vetted, DPA compliant vendors. We do store all conversation and personal data
|
|
||||||
for up to 6 years unless your account is deleted. In which case, we dispose of all data in accordance with our
|
|
||||||
Terms of Service and Privacy Policy, but we will not hold it longer than 60 days.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
We are aware that if you are working with EU customers, you need to be able to provide them with the ability to
|
|
||||||
access, update, retrieve and remove personal data. We got you! We’ve been set up as self service from the
|
|
||||||
start and have always given you access to your data. Our customer support team is here for you to answer any
|
|
||||||
questions you might have about working with the API.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4>California Residents</h4>
|
|
||||||
<p>
|
|
||||||
The California Consumer Privacy Act (CCPA) requires us to disclose categories of Personal Information we collect
|
|
||||||
and how we use it, the categories of sources from whom we collect Personal Information, and the third parties with
|
|
||||||
whom we share it, which we have explained above.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
We are also required to communicate information about rights California residents have under California law. You
|
|
||||||
may exercise the following rights:
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Right to Know and Access. You may submit a verifiable request for information regarding the: (1) categories of
|
|
||||||
Personal Information we collect, use, or share; (2) purposes for which categories of Personal Information are
|
|
||||||
collected or used by us; (3) categories of sources from which we collect Personal Information; and (4) specific
|
|
||||||
pieces of Personal Information we have collected about you.
|
|
||||||
</li>
|
|
||||||
<li>Right to Equal Service. We will not discriminate against you if you exercise your privacy rights.</li>
|
|
||||||
<li>
|
|
||||||
Right to Delete. You may submit a verifiable request to close your account and we will delete Personal
|
|
||||||
Information about you that we have collected.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Request that a business that sells a consumer’s personal data, not sell the consumer’s personal
|
|
||||||
data.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p>
|
|
||||||
If you make a request, we have one month to respond to you. If you would like to exercise any of these rights,
|
|
||||||
please contact us.
|
|
||||||
</p>
|
|
||||||
<p>We do not sell the Personal Information of our users.</p>
|
|
||||||
<p>For more information about these rights, please contact us.</p>
|
|
||||||
|
|
||||||
<h5>California Online Privacy Protection Act (CalOPPA)</h5>
|
|
||||||
<p>
|
|
||||||
CalOPPA requires us to disclose categories of Personal Information we collect and how we use it, the categories of
|
|
||||||
sources from whom we collect Personal Information, and the third parties with whom we share it, which we have
|
|
||||||
explained above.
|
|
||||||
</p>
|
|
||||||
<p>CalOPPA users have the following rights:</p>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
Right to Know and Access. You may submit a verifiable request for information regarding the: (1) categories of
|
|
||||||
Personal Information we collect, use, or share; (2) purposes for which categories of Personal Information are
|
|
||||||
collected or used by us; (3) categories of sources from which we collect Personal Information; and (4) specific
|
|
||||||
pieces of Personal Information we have collected about you.
|
|
||||||
</li>
|
|
||||||
<li>Right to Equal Service. We will not discriminate against you if you exercise your privacy rights.</li>
|
|
||||||
<li>
|
|
||||||
Right to Delete. You may submit a verifiable request to close your account and we will delete Personal
|
|
||||||
Information about you that we have collected.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Right to request that a business that sells a consumer’s personal data, not sell the consumer’s
|
|
||||||
personal data.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p>
|
|
||||||
If you make a request, we have one month to respond to you. If you would like to exercise any of these rights,
|
|
||||||
please contact us.
|
|
||||||
</p>
|
|
||||||
<p>We do not sell the Personal Information of our users.</p>
|
|
||||||
<p>For more information about these rights, please contact us.</p>
|
|
||||||
|
|
||||||
<h4>Contact Us</h4>
|
|
||||||
<p>Don’t hesitate to contact us if you have any questions.</p>
|
|
||||||
<ul>
|
|
||||||
<li>Via this Link: <router-link to="/how-it-works">https://noagendacareers.com/how-it-works</router-link></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<p class="fst-italic">
|
|
||||||
Changes on August 30<sup>th</sup>, 2022
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
<li class="fst-italic">Removed references to Mastodon</li>
|
|
||||||
<li class="fst-italic">Added references to job listings</li>
|
|
||||||
<li class="fst-italic">Changed information regarding e-mail addresses</li>
|
|
||||||
</ul>
|
|
||||||
<p class="fst-italic">
|
|
||||||
Change on September 6<sup>th</sup>, 2021 – replaced “No Agenda Social” with generic terms for
|
|
||||||
any authorized Mastodon instance.
|
|
||||||
</p>
|
|
||||||
</article>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
/** The name of the application */
|
|
||||||
const name = "Jobs, Jobs, Jobs"
|
|
||||||
</script>
|
|
|
@ -1,44 +0,0 @@
|
||||||
<template>
|
|
||||||
<article>
|
|
||||||
<h3>Terms of Service</h3>
|
|
||||||
<p class="fst-italic">(as of August 30<sup>th</sup>, 2022)</p>
|
|
||||||
<h4>Acceptance of Terms</h4>
|
|
||||||
<p>
|
|
||||||
By accessing this web site, you are agreeing to be bound by these Terms and Conditions, and that you are
|
|
||||||
responsible to ensure that your use of this site complies with all applicable laws. Your continued use of this
|
|
||||||
site implies your acceptance of these terms.
|
|
||||||
</p>
|
|
||||||
<h4>Description of Service and Registration</h4>
|
|
||||||
<p>
|
|
||||||
Jobs, Jobs, Jobs is a service that allows individuals to enter and amend employment profiles and job listings,
|
|
||||||
restricting access to the details of these to other users of this site, unless the individual specifies that this
|
|
||||||
information should be visible publicly. See our <router-link to="/privacy-policy">privacy policy</router-link> for
|
|
||||||
details on the personal (user) information we maintain.
|
|
||||||
</p>
|
|
||||||
<h4>Liability</h4>
|
|
||||||
<p>
|
|
||||||
This service is provided “as is”, and no warranty (express or implied) exists. The service and its
|
|
||||||
developers may not be held liable for any damages that may arise through the use of this service.
|
|
||||||
</p>
|
|
||||||
<h4>Updates to Terms</h4>
|
|
||||||
<p>
|
|
||||||
These terms and conditions may be updated at any time. When these terms are updated, users will be notified via a
|
|
||||||
notice on the dashboard page. Additionally, the date at the top of this page will be updated, and any substantive
|
|
||||||
updates will also be accompanied by a summary of those changes.
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
<p>
|
|
||||||
You may also wish to review our <router-link to="/privacy-policy">privacy policy</router-link> to learn how we
|
|
||||||
handle your data.
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
<p class="fst-italic">
|
|
||||||
Change on August 30<sup>th</sup>, 2022 – added references to job listings, removed references to Mastodon
|
|
||||||
instances.
|
|
||||||
</p>
|
|
||||||
<p class="fst-italic">
|
|
||||||
Change on September 6<sup>th</sup>, 2021 – replaced “No Agenda Social” with a list of all No
|
|
||||||
Agenda-affiliated Mastodon instances.
|
|
||||||
</p>
|
|
||||||
</article>
|
|
||||||
</template>
|
|
|
@ -1,126 +0,0 @@
|
||||||
<template>
|
|
||||||
<article>
|
|
||||||
<h3 class="pb-3">People Seeking Work</h3>
|
|
||||||
<p v-if="!searched">
|
|
||||||
Enter one or more criteria to filter results, or just click “Search” to list all profiles.
|
|
||||||
</p>
|
|
||||||
<collapse-panel headerText="Search Criteria" :collapsed="isCollapsed" @toggle="toggleCollapse">
|
|
||||||
<profile-public-search-form v-model="criteria" @search="doSearch" />
|
|
||||||
</collapse-panel>
|
|
||||||
<error-list :errors="errors">
|
|
||||||
<p v-if="searching">Searching profiles…</p>
|
|
||||||
<template v-else>
|
|
||||||
<template v-if="results.length > 0">
|
|
||||||
<p class="py-3">
|
|
||||||
These profiles match your search criteria. To learn more about these people, join the merry band of human
|
|
||||||
resources in the <a href="https://noagendashow.net" target="_blank" rel="noopener">No Agenda</a> tribe!
|
|
||||||
</p>
|
|
||||||
<table class="table table-sm table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th scope="col">Continent</th>
|
|
||||||
<th class="text-center" scope="col">Region</th>
|
|
||||||
<th class="text-center" scope="col">Remote?</th>
|
|
||||||
<th class="text-center" scope="col">Skills</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr v-for="(profile, idx) in results" :key="idx">
|
|
||||||
<td>{{profile.continent}}</td>
|
|
||||||
<td>{{profile.region}}</td>
|
|
||||||
<td class="text-center">{{yesOrNo(profile.remoteWork)}}</td>
|
|
||||||
<td><template v-for="(skill, idx) in profile.skills" :key="idx">{{skill}}<br></template></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</template>
|
|
||||||
<p v-else-if="searched" class="pt-3">No results found for the specified criteria</p>
|
|
||||||
</template>
|
|
||||||
</error-list>
|
|
||||||
</article>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { Ref, ref, watch } from "vue"
|
|
||||||
import { useRoute, useRouter } from "vue-router"
|
|
||||||
import { yesOrNo } from "@/App.vue"
|
|
||||||
import api, { PublicSearch, PublicSearchResult } from "@/api"
|
|
||||||
import { queryValue } from "@/router"
|
|
||||||
|
|
||||||
import CollapsePanel from "@/components/CollapsePanel.vue"
|
|
||||||
import ErrorList from "@/components/ErrorList.vue"
|
|
||||||
import ProfilePublicSearchForm from "@/components/profile/PublicSearchForm.vue"
|
|
||||||
|
|
||||||
const route = useRoute()
|
|
||||||
const router = useRouter()
|
|
||||||
|
|
||||||
/** Whether a search has been performed */
|
|
||||||
const searched = ref(false)
|
|
||||||
|
|
||||||
/** Indicates whether a request for matching profiles is in progress */
|
|
||||||
const searching = ref(false)
|
|
||||||
|
|
||||||
/** Error messages encountered while searching for profiles */
|
|
||||||
const errors : Ref<string[]> = ref([])
|
|
||||||
|
|
||||||
/** An empty set of search criteria */
|
|
||||||
const emptyCriteria = {
|
|
||||||
continentId: "",
|
|
||||||
region: undefined,
|
|
||||||
skill: undefined,
|
|
||||||
remoteWork: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The search criteria being built from the page */
|
|
||||||
const criteria : Ref<PublicSearch> = ref(emptyCriteria)
|
|
||||||
|
|
||||||
/** The search results */
|
|
||||||
const results : Ref<PublicSearchResult[]> = ref([])
|
|
||||||
|
|
||||||
/** Whether the search results are collapsed */
|
|
||||||
const isCollapsed = ref(searched.value && results.value.length > 0)
|
|
||||||
|
|
||||||
/** Set up the page to match its requested state */
|
|
||||||
const setUpPage = async () => {
|
|
||||||
if (queryValue(route, "searched") === "true") {
|
|
||||||
searched.value = true
|
|
||||||
try {
|
|
||||||
searching.value = true
|
|
||||||
const contId = queryValue(route, "continentId")
|
|
||||||
const searchParams : PublicSearch = {
|
|
||||||
continentId: contId === "" ? undefined : contId,
|
|
||||||
region: queryValue(route, "region"),
|
|
||||||
skill: queryValue(route, "skill"),
|
|
||||||
remoteWork: queryValue(route, "remoteWork") ?? ""
|
|
||||||
}
|
|
||||||
const searchResult = await api.profile.publicSearch(searchParams)
|
|
||||||
if (typeof searchResult === "string") {
|
|
||||||
errors.value.push(searchResult)
|
|
||||||
} else if (searchResult === undefined) {
|
|
||||||
errors.value.push(`The server returned a "Not Found" response (this should not happen)`)
|
|
||||||
} else {
|
|
||||||
results.value = searchResult
|
|
||||||
searchParams.continentId = searchParams.continentId ?? ""
|
|
||||||
criteria.value = searchParams
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
searching.value = false
|
|
||||||
}
|
|
||||||
isCollapsed.value = searched.value && results.value.length > 0
|
|
||||||
} else {
|
|
||||||
searched.value = false
|
|
||||||
criteria.value = emptyCriteria
|
|
||||||
errors.value = []
|
|
||||||
results.value = []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Refresh the page when the query string changes */
|
|
||||||
watch(() => route.query, setUpPage, { immediate: true })
|
|
||||||
|
|
||||||
/** Open and closed the search parameter panel */
|
|
||||||
const toggleCollapse = (it : boolean) => { isCollapsed.value = it }
|
|
||||||
|
|
||||||
/** Execute a search */
|
|
||||||
const doSearch = () => router.push({ query: { searched: "true", ...criteria.value } })
|
|
||||||
</script>
|
|
|
@ -483,29 +483,29 @@ module Profiles =
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search profiles (public)
|
// Search profiles (public)
|
||||||
let publicSearch (search : PublicSearch) =
|
let publicSearch (search : PublicSearchForm) =
|
||||||
let searches = [
|
let searches = [
|
||||||
match search.ContinentId with
|
if search.ContinentId <> "" then
|
||||||
| Some contId -> "p.data ->> 'continentId' = @continentId", [ "@continentId", Sql.string contId ]
|
"p.data ->> 'continentId' = @continentId", [ "@continentId", Sql.string search.ContinentId ]
|
||||||
| None -> ()
|
if search.Region <> "" then
|
||||||
match search.Region with
|
"p.data ->> 'region' ILIKE @region", [ "@region", like search.Region ]
|
||||||
| Some region -> "p.data ->> 'region' ILIKE @region", [ "@region", like region ]
|
|
||||||
| None -> ()
|
|
||||||
if search.RemoteWork <> "" then
|
if search.RemoteWork <> "" then
|
||||||
"p.data ->> 'remoteWork' = @remote", [ "@remote", jsonBool (search.RemoteWork = "yes") ]
|
"p.data ->> 'isRemote' = @remote", [ "@remote", jsonBool (search.RemoteWork = "yes") ]
|
||||||
match search.Skill with
|
if search.Skill <> "" then
|
||||||
| Some skl ->
|
"EXISTS (
|
||||||
"p.data -> 'skills' ->> 'description' ILIKE @description", [ "@description", like skl ]
|
SELECT 1 FROM jsonb_array_elements(p.data['skills']) x(elt)
|
||||||
| None -> ()
|
WHERE x ->> 'description' ILIKE @description)",
|
||||||
|
[ "@description", like search.Skill ]
|
||||||
]
|
]
|
||||||
connection ()
|
connection ()
|
||||||
|> Sql.query $"
|
|> Sql.query $"
|
||||||
SELECT p.*, c.data AS cont_data
|
SELECT p.*, c.data AS cont_data
|
||||||
FROM {Table.Profile} p
|
FROM {Table.Profile} p
|
||||||
INNER JOIN {Table.Continent} c ON c.id = p.data ->> 'continentId'
|
INNER JOIN {Table.Continent} c ON c.id = p.data ->> 'continentId'
|
||||||
WHERE p.data ->> 'isPublic' = 'true'
|
WHERE p.data ->> 'isPubliclySearchable' = 'true'
|
||||||
AND p.data ->> 'isLegacy' = 'false'
|
AND p.data ->> 'isLegacy' = 'false'
|
||||||
{searchSql searches}"
|
{searchSql searches}"
|
||||||
|
|> Sql.parameters (searches |> List.collect snd)
|
||||||
|> Sql.executeAsync (fun row ->
|
|> Sql.executeAsync (fun row ->
|
||||||
let profile = toDocument<Profile> row
|
let profile = toDocument<Profile> row
|
||||||
let continent = toDocumentFrom<Continent> "cont_data" row
|
let continent = toDocumentFrom<Continent> "cont_data" row
|
||||||
|
|
|
@ -218,31 +218,20 @@ type ProfileForView =
|
||||||
|
|
||||||
/// The parameters for a public job search
|
/// The parameters for a public job search
|
||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
type PublicSearch =
|
type PublicSearchForm =
|
||||||
{ /// Retrieve citizens from this continent
|
{ /// Retrieve citizens from this continent
|
||||||
ContinentId : string option
|
ContinentId : string
|
||||||
|
|
||||||
/// Retrieve citizens from this region
|
/// Retrieve citizens from this region
|
||||||
Region : string option
|
Region : string
|
||||||
|
|
||||||
/// Text for a search within a citizen's skills
|
/// Text for a search within a citizen's skills
|
||||||
Skill : string option
|
Skill : string
|
||||||
|
|
||||||
/// Whether to retrieve citizens who do or do not want remote work
|
/// Whether to retrieve citizens who do or do not want remote work
|
||||||
RemoteWork : string
|
RemoteWork : string
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Support functions for public searches
|
|
||||||
module PublicSearch =
|
|
||||||
/// Is the search empty?
|
|
||||||
let isEmptySearch (search : PublicSearch) =
|
|
||||||
[ search.ContinentId
|
|
||||||
search.Region
|
|
||||||
search.Skill
|
|
||||||
if search.RemoteWork = "" then Some search.RemoteWork else None
|
|
||||||
]
|
|
||||||
|> List.exists Option.isSome
|
|
||||||
|
|
||||||
|
|
||||||
/// A public profile search result
|
/// A public profile search result
|
||||||
type PublicSearchResult =
|
type PublicSearchResult =
|
||||||
|
|
|
@ -663,6 +663,22 @@ module Profile =
|
||||||
return! Profile.search form continents (timeZone ctx) results |> render "Profile Search" next ctx
|
return! Profile.search form continents (timeZone ctx) results |> render "Profile Search" next ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GET: /profile/seeking
|
||||||
|
let seeking : HttpHandler = fun next ctx -> task {
|
||||||
|
let! continents = Continents.all ()
|
||||||
|
let form =
|
||||||
|
match ctx.TryBindQueryString<PublicSearchForm> () with
|
||||||
|
| Ok f -> f
|
||||||
|
| Error _ -> { ContinentId = ""; Region = ""; RemoteWork = ""; Skill = "" }
|
||||||
|
let! results = task {
|
||||||
|
if string ctx.Request.Query["searched"] = "true" then
|
||||||
|
let! it = Profiles.publicSearch form
|
||||||
|
return Some it
|
||||||
|
else return None
|
||||||
|
}
|
||||||
|
return! Profile.publicSearch form continents results |> render "Profile Search" next ctx
|
||||||
|
}
|
||||||
|
|
||||||
// GET: /profile/[id]/view
|
// GET: /profile/[id]/view
|
||||||
let view citizenId : HttpHandler = fun next ctx -> task {
|
let view citizenId : HttpHandler = fun next ctx -> task {
|
||||||
let citId = CitizenId.ofString citizenId
|
let citId = CitizenId.ofString citizenId
|
||||||
|
@ -732,13 +748,6 @@ module ProfileApi =
|
||||||
do! Profiles.deleteById (currentCitizenId ctx)
|
do! Profiles.deleteById (currentCitizenId ctx)
|
||||||
return! ok next ctx
|
return! ok next ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET: /api/profile/public-search
|
|
||||||
let publicSearch : HttpHandler = fun next ctx -> task {
|
|
||||||
let search = ctx.BindQueryString<PublicSearch> ()
|
|
||||||
let! results = Profiles.publicSearch search
|
|
||||||
return! json results next ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Handlers for /api/success routes
|
/// Handlers for /api/success routes
|
||||||
|
@ -815,6 +824,7 @@ let allEndpoints = [
|
||||||
routef "/%s/view" Profile.view
|
routef "/%s/view" Profile.view
|
||||||
route "/edit" Profile.edit
|
route "/edit" Profile.edit
|
||||||
route "/search" Profile.search
|
route "/search" Profile.search
|
||||||
|
route "/seeking" Profile.seeking
|
||||||
]
|
]
|
||||||
POST [ route "/save" Profile.save ]
|
POST [ route "/save" Profile.save ]
|
||||||
]
|
]
|
||||||
|
@ -848,8 +858,6 @@ let allEndpoints = [
|
||||||
route "" ProfileApi.current
|
route "" ProfileApi.current
|
||||||
route "/count" ProfileApi.count
|
route "/count" ProfileApi.count
|
||||||
routef "/%O" ProfileApi.get
|
routef "/%O" ProfileApi.get
|
||||||
routef "/%O/view" ProfileApi.view
|
|
||||||
route "/public-search" ProfileApi.publicSearch
|
|
||||||
]
|
]
|
||||||
PATCH [ route "/employment-found" ProfileApi.employmentFound ]
|
PATCH [ route "/employment-found" ProfileApi.employmentFound ]
|
||||||
]
|
]
|
||||||
|
|
|
@ -127,6 +127,90 @@ let edit (m : EditProfileViewModel) continents isNew citizenId csrf =
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
/// The public search page
|
||||||
|
let publicSearch (m : PublicSearchForm) continents (results : PublicSearchResult list option) =
|
||||||
|
article [] [
|
||||||
|
h3 [ _class "pb-3" ] [ rawText "People Seeking Work" ]
|
||||||
|
if Option.isNone results then
|
||||||
|
p [] [
|
||||||
|
rawText "Enter one or more criteria to filter results, or just click “Search” to list all "
|
||||||
|
rawText "publicly searchable profiles."
|
||||||
|
]
|
||||||
|
collapsePanel "Search Criteria" [
|
||||||
|
form [ _class "container"; _method "GET"; _action "/profile/seeking" ] [
|
||||||
|
input [ _type "hidden"; _name "searched"; _value "true" ]
|
||||||
|
div [ _class "row" ] [
|
||||||
|
div [ _class "col-12 col-sm-6 col-md-4 col-lg-3" ] [
|
||||||
|
continentList [] "ContinentId" continents (Some "Any") m.ContinentId false
|
||||||
|
]
|
||||||
|
div [ _class "col-12 col-sm-6 col-md-4 col-lg-3" ] [
|
||||||
|
textBox [ _maxlength "1000" ] (nameof m.Region) m.Region "Region" false
|
||||||
|
div [ _class "form-text" ] [ rawText "(free-form text)" ]
|
||||||
|
]
|
||||||
|
div [ _class "col-12 col-sm-6 col-offset-md-2 col-lg-3 col-offset-lg-0" ] [
|
||||||
|
label [ _class "jjj-label" ] [ rawText "Seeking Remote Work?" ]; br []
|
||||||
|
div [ _class "form-check form-check-inline" ] [
|
||||||
|
input [ _type "radio"; _id "remoteNull"; _name (nameof m.RemoteWork); _value ""
|
||||||
|
_class "form-check-input"; if m.RemoteWork = "" then _checked ]
|
||||||
|
label [ _class "form-check-label"; _for "remoteNull" ] [ rawText "No Selection" ]
|
||||||
|
]
|
||||||
|
div [ _class "form-check form-check-inline" ] [
|
||||||
|
input [ _type "radio"; _id "remoteYes"; _name (nameof m.RemoteWork); _value "yes"
|
||||||
|
_class "form-check-input"; if m.RemoteWork = "yes" then _checked ]
|
||||||
|
label [ _class "form-check-label"; _for "remoteYes" ] [ rawText "Yes" ]
|
||||||
|
]
|
||||||
|
div [ _class "form-check form-check-inline" ] [
|
||||||
|
input [ _type "radio"; _id "remoteNo"; _name (nameof m.RemoteWork); _value "no"
|
||||||
|
_class "form-check-input"; if m.RemoteWork = "no" then _checked ]
|
||||||
|
label [ _class "form-check-label"; _for "remoteNo" ] [ rawText "No" ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
div [ _class "col-12 col-sm-6 col-lg-3" ] [
|
||||||
|
textBox [ _maxlength "1000" ] (nameof m.Skill) m.Skill "Skill" false
|
||||||
|
div [ _class "form-text" ] [ rawText "(free-form text)" ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
div [ _class "row" ] [
|
||||||
|
div [ _class "col" ] [
|
||||||
|
br []
|
||||||
|
button [ _type "submit"; _class "btn btn-outline-primary" ] [ rawText "Search" ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
match results with
|
||||||
|
| Some r when List.isEmpty r -> p [ _class "pt-3" ] [ rawText "No results found for the specified criteria" ]
|
||||||
|
| Some r ->
|
||||||
|
p [ _class "py-3" ] [
|
||||||
|
rawText "These profiles match your search criteria. To learn more about these people, join the merry "
|
||||||
|
rawText "band of human resources in the "
|
||||||
|
a [ _href "https://noagendashow.net"; _target "_blank"; _rel "noopener" ] [ rawText "No Agenda" ]
|
||||||
|
rawText " tribe!"
|
||||||
|
]
|
||||||
|
table [ _class "table table-sm table-hover" ] [
|
||||||
|
thead [] [
|
||||||
|
tr [] [
|
||||||
|
th [ _scope "col" ] [ rawText "Continent" ]
|
||||||
|
th [ _scope "col"; _class "text-center" ] [ rawText "Region" ]
|
||||||
|
th [ _scope "col"; _class "text-center" ] [ rawText "Remote?" ]
|
||||||
|
th [ _scope "col"; _class "text-center" ] [ rawText "Skills" ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
r |> List.map (fun profile ->
|
||||||
|
tr [] [
|
||||||
|
td [] [ str profile.Continent ]
|
||||||
|
td [] [ str profile.Region ]
|
||||||
|
td [ _class "text-center" ] [ rawText (yesOrNo profile.RemoteWork) ]
|
||||||
|
profile.Skills
|
||||||
|
|> List.collect (fun skill -> [ str skill; br [] ])
|
||||||
|
|> td []
|
||||||
|
])
|
||||||
|
|> tbody []
|
||||||
|
]
|
||||||
|
| None -> ()
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
/// Logged-on search page
|
/// Logged-on search page
|
||||||
let search (m : ProfileSearchForm) continents tz (results : ProfileSearchResult list option) =
|
let search (m : ProfileSearchForm) continents tz (results : ProfileSearchResult list option) =
|
||||||
article [] [
|
article [] [
|
||||||
|
|
Loading…
Reference in New Issue
Block a user