From 2957c94120028a962f61f8109a16df5d32b483a7 Mon Sep 17 00:00:00 2001 From: Rhodine Orleans-Lindsay Date: Thu, 13 Aug 2020 17:51:58 +0100 Subject: [PATCH 1/2] non admin user only sees their projects, admin user sees full list of projects with theirs at the top noted with a 'Member' badge Unit testing projects-list and clean up of project-list component and html. updated packages greyed out projects not belonging to admin Non-admin view now matches admin view ordered projects alphabetically - user pr ojects priotised amended projects-list unit test. squashing commits amended test alphabetical order now accounts for lower case --- platform-hub-api/db/structure.sql | 292 +++++++++--------- platform-hub-web/package.json | 2 +- .../app/projects/projects-list.component.js | 69 ++++- .../projects/projects-list.component.spec.js | 111 +++++++ .../src/app/projects/projects-list.html | 6 +- .../src/app/shared/model/projects.js | 1 + 6 files changed, 323 insertions(+), 158 deletions(-) create mode 100644 platform-hub-web/src/app/projects/projects-list.component.spec.js diff --git a/platform-hub-api/db/structure.sql b/platform-hub-api/db/structure.sql index 87d21e31..de09352a 100644 --- a/platform-hub-api/db/structure.sql +++ b/platform-hub-api/db/structure.sql @@ -3,14 +3,16 @@ -- -- Dumped from database version 9.6.1 --- Dumped by pg_dump version 9.6.2 +-- Dumped by pg_dump version 9.6.17 SET statement_timeout = 0; SET lock_timeout = 0; SET idle_in_transaction_session_timeout = 0; SET client_encoding = 'UTF8'; SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); SET check_function_bodies = false; +SET xmloption = content; SET client_min_messages = warning; SET row_security = off; @@ -56,8 +58,6 @@ CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA public; COMMENT ON EXTENSION "uuid-ossp" IS 'generate universally unique identifiers (UUIDs)'; -SET search_path = public, pg_catalog; - SET default_tablespace = ''; SET default_with_oids = false; @@ -66,8 +66,8 @@ SET default_with_oids = false; -- Name: allocations; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE allocations ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.allocations ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, allocatable_type character varying NOT NULL, allocatable_id uuid NOT NULL, allocation_receivable_type character varying NOT NULL, @@ -81,8 +81,8 @@ CREATE TABLE allocations ( -- Name: announcement_templates; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE announcement_templates ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.announcement_templates ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, shortname character varying NOT NULL, slug character varying NOT NULL, description text, @@ -96,8 +96,8 @@ CREATE TABLE announcement_templates ( -- Name: announcements; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE announcements ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.announcements ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, level character varying NOT NULL, title character varying, text text, @@ -118,7 +118,7 @@ CREATE TABLE announcements ( -- Name: ar_internal_metadata; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE ar_internal_metadata ( +CREATE TABLE public.ar_internal_metadata ( key character varying NOT NULL, value character varying, created_at timestamp without time zone NOT NULL, @@ -130,7 +130,7 @@ CREATE TABLE ar_internal_metadata ( -- Name: audits; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE audits ( +CREATE TABLE public.audits ( id integer NOT NULL, auditable_type character varying, auditable_id uuid, @@ -154,7 +154,7 @@ CREATE TABLE audits ( -- Name: audits_id_seq; Type: SEQUENCE; Schema: public; Owner: - -- -CREATE SEQUENCE audits_id_seq +CREATE SEQUENCE public.audits_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -166,14 +166,14 @@ CREATE SEQUENCE audits_id_seq -- Name: audits_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - -- -ALTER SEQUENCE audits_id_seq OWNED BY audits.id; +ALTER SEQUENCE public.audits_id_seq OWNED BY public.audits.id; -- -- Name: contact_lists; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE contact_lists ( +CREATE TABLE public.contact_lists ( id character varying NOT NULL, email_addresses character varying[], created_at timestamp without time zone NOT NULL, @@ -185,7 +185,7 @@ CREATE TABLE contact_lists ( -- Name: costs_reports; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE costs_reports ( +CREATE TABLE public.costs_reports ( id character varying NOT NULL, year integer NOT NULL, month character varying NOT NULL, @@ -204,7 +204,7 @@ CREATE TABLE costs_reports ( -- Name: delayed_jobs; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE delayed_jobs ( +CREATE TABLE public.delayed_jobs ( id integer NOT NULL, priority integer DEFAULT 0 NOT NULL, attempts integer DEFAULT 0 NOT NULL, @@ -224,7 +224,7 @@ CREATE TABLE delayed_jobs ( -- Name: delayed_jobs_id_seq; Type: SEQUENCE; Schema: public; Owner: - -- -CREATE SEQUENCE delayed_jobs_id_seq +CREATE SEQUENCE public.delayed_jobs_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -236,15 +236,15 @@ CREATE SEQUENCE delayed_jobs_id_seq -- Name: delayed_jobs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - -- -ALTER SEQUENCE delayed_jobs_id_seq OWNED BY delayed_jobs.id; +ALTER SEQUENCE public.delayed_jobs_id_seq OWNED BY public.delayed_jobs.id; -- -- Name: docker_repos; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE docker_repos ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.docker_repos ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, name character varying NOT NULL, description text, service_id uuid NOT NULL, @@ -261,8 +261,8 @@ CREATE TABLE docker_repos ( -- Name: docs_source_entries; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE docs_source_entries ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.docs_source_entries ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, docs_source_id uuid NOT NULL, content_id character varying NOT NULL, content_url character varying NOT NULL, @@ -276,8 +276,8 @@ CREATE TABLE docs_source_entries ( -- Name: docs_sources; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE docs_sources ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.docs_sources ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, kind character varying NOT NULL, name character varying NOT NULL, config json NOT NULL, @@ -296,7 +296,7 @@ CREATE TABLE docs_sources ( -- Name: hash_records; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE hash_records ( +CREATE TABLE public.hash_records ( id character varying NOT NULL, scope character varying NOT NULL, data json NOT NULL, @@ -309,8 +309,8 @@ CREATE TABLE hash_records ( -- Name: identities; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE identities ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.identities ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, user_id uuid NOT NULL, provider character varying NOT NULL, external_id character varying NOT NULL, @@ -327,8 +327,8 @@ CREATE TABLE identities ( -- Name: kubernetes_clusters; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE kubernetes_clusters ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.kubernetes_clusters ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, name character varying NOT NULL, description text NOT NULL, s3_region character varying, @@ -352,8 +352,8 @@ CREATE TABLE kubernetes_clusters ( -- Name: kubernetes_groups; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE kubernetes_groups ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.kubernetes_groups ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, name character varying NOT NULL, kind character varying NOT NULL, target character varying NOT NULL, @@ -369,8 +369,8 @@ CREATE TABLE kubernetes_groups ( -- Name: kubernetes_namespaces; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE kubernetes_namespaces ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.kubernetes_namespaces ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, service_id uuid NOT NULL, cluster_id uuid NOT NULL, name character varying NOT NULL, @@ -384,8 +384,8 @@ CREATE TABLE kubernetes_namespaces ( -- Name: kubernetes_tokens; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE kubernetes_tokens ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.kubernetes_tokens ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, tokenable_type character varying NOT NULL, tokenable_id uuid NOT NULL, cluster_id uuid NOT NULL, @@ -406,8 +406,8 @@ CREATE TABLE kubernetes_tokens ( -- Name: platform_themes; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE platform_themes ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.platform_themes ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, title character varying NOT NULL, slug character varying NOT NULL, description text NOT NULL, @@ -423,7 +423,7 @@ CREATE TABLE platform_themes ( -- Name: project_memberships; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE project_memberships ( +CREATE TABLE public.project_memberships ( project_id uuid NOT NULL, user_id uuid NOT NULL, role character varying, @@ -436,8 +436,8 @@ CREATE TABLE project_memberships ( -- Name: projects; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE projects ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.projects ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, shortname character varying NOT NULL, slug character varying NOT NULL, name character varying NOT NULL, @@ -452,8 +452,8 @@ CREATE TABLE projects ( -- Name: qa_entries; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE qa_entries ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.qa_entries ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, question character varying NOT NULL, answer text NOT NULL, created_at timestamp without time zone NOT NULL, @@ -465,7 +465,7 @@ CREATE TABLE qa_entries ( -- Name: read_marks; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE read_marks ( +CREATE TABLE public.read_marks ( id integer NOT NULL, readable_type character varying NOT NULL, readable_id uuid, @@ -479,7 +479,7 @@ CREATE TABLE read_marks ( -- Name: read_marks_id_seq; Type: SEQUENCE; Schema: public; Owner: - -- -CREATE SEQUENCE read_marks_id_seq +CREATE SEQUENCE public.read_marks_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -491,14 +491,14 @@ CREATE SEQUENCE read_marks_id_seq -- Name: read_marks_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - -- -ALTER SEQUENCE read_marks_id_seq OWNED BY read_marks.id; +ALTER SEQUENCE public.read_marks_id_seq OWNED BY public.read_marks.id; -- -- Name: schema_migrations; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE schema_migrations ( +CREATE TABLE public.schema_migrations ( version character varying NOT NULL ); @@ -507,8 +507,8 @@ CREATE TABLE schema_migrations ( -- Name: services; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE services ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.services ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, name character varying NOT NULL, description text NOT NULL, project_id uuid NOT NULL, @@ -521,8 +521,8 @@ CREATE TABLE services ( -- Name: support_request_templates; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE support_request_templates ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.support_request_templates ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, shortname character varying NOT NULL, slug character varying NOT NULL, git_hub_repo character varying NOT NULL, @@ -540,8 +540,8 @@ CREATE TABLE support_request_templates ( -- Name: user_flags; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE user_flags ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.user_flags ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, completed_hub_onboarding boolean DEFAULT false, created_at timestamp without time zone NOT NULL, updated_at timestamp without time zone NOT NULL, @@ -554,8 +554,8 @@ CREATE TABLE user_flags ( -- Name: users; Type: TABLE; Schema: public; Owner: - -- -CREATE TABLE users ( - id uuid DEFAULT uuid_generate_v4() NOT NULL, +CREATE TABLE public.users ( + id uuid DEFAULT public.uuid_generate_v4() NOT NULL, name character varying NOT NULL, email character varying NOT NULL, last_seen_at timestamp without time zone, @@ -572,28 +572,28 @@ CREATE TABLE users ( -- Name: audits id; Type: DEFAULT; Schema: public; Owner: - -- -ALTER TABLE ONLY audits ALTER COLUMN id SET DEFAULT nextval('audits_id_seq'::regclass); +ALTER TABLE ONLY public.audits ALTER COLUMN id SET DEFAULT nextval('public.audits_id_seq'::regclass); -- -- Name: delayed_jobs id; Type: DEFAULT; Schema: public; Owner: - -- -ALTER TABLE ONLY delayed_jobs ALTER COLUMN id SET DEFAULT nextval('delayed_jobs_id_seq'::regclass); +ALTER TABLE ONLY public.delayed_jobs ALTER COLUMN id SET DEFAULT nextval('public.delayed_jobs_id_seq'::regclass); -- -- Name: read_marks id; Type: DEFAULT; Schema: public; Owner: - -- -ALTER TABLE ONLY read_marks ALTER COLUMN id SET DEFAULT nextval('read_marks_id_seq'::regclass); +ALTER TABLE ONLY public.read_marks ALTER COLUMN id SET DEFAULT nextval('public.read_marks_id_seq'::regclass); -- -- Name: allocations allocations_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY allocations +ALTER TABLE ONLY public.allocations ADD CONSTRAINT allocations_pkey PRIMARY KEY (id); @@ -601,7 +601,7 @@ ALTER TABLE ONLY allocations -- Name: announcement_templates announcement_templates_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY announcement_templates +ALTER TABLE ONLY public.announcement_templates ADD CONSTRAINT announcement_templates_pkey PRIMARY KEY (id); @@ -609,7 +609,7 @@ ALTER TABLE ONLY announcement_templates -- Name: announcements announcements_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY announcements +ALTER TABLE ONLY public.announcements ADD CONSTRAINT announcements_pkey PRIMARY KEY (id); @@ -617,7 +617,7 @@ ALTER TABLE ONLY announcements -- Name: ar_internal_metadata ar_internal_metadata_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY ar_internal_metadata +ALTER TABLE ONLY public.ar_internal_metadata ADD CONSTRAINT ar_internal_metadata_pkey PRIMARY KEY (key); @@ -625,7 +625,7 @@ ALTER TABLE ONLY ar_internal_metadata -- Name: audits audits_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY audits +ALTER TABLE ONLY public.audits ADD CONSTRAINT audits_pkey PRIMARY KEY (id); @@ -633,7 +633,7 @@ ALTER TABLE ONLY audits -- Name: contact_lists contact_lists_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY contact_lists +ALTER TABLE ONLY public.contact_lists ADD CONSTRAINT contact_lists_pkey PRIMARY KEY (id); @@ -641,7 +641,7 @@ ALTER TABLE ONLY contact_lists -- Name: costs_reports costs_reports_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY costs_reports +ALTER TABLE ONLY public.costs_reports ADD CONSTRAINT costs_reports_pkey PRIMARY KEY (id); @@ -649,7 +649,7 @@ ALTER TABLE ONLY costs_reports -- Name: delayed_jobs delayed_jobs_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY delayed_jobs +ALTER TABLE ONLY public.delayed_jobs ADD CONSTRAINT delayed_jobs_pkey PRIMARY KEY (id); @@ -657,7 +657,7 @@ ALTER TABLE ONLY delayed_jobs -- Name: docker_repos docker_repos_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY docker_repos +ALTER TABLE ONLY public.docker_repos ADD CONSTRAINT docker_repos_pkey PRIMARY KEY (id); @@ -665,7 +665,7 @@ ALTER TABLE ONLY docker_repos -- Name: docs_source_entries docs_source_entries_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY docs_source_entries +ALTER TABLE ONLY public.docs_source_entries ADD CONSTRAINT docs_source_entries_pkey PRIMARY KEY (id); @@ -673,7 +673,7 @@ ALTER TABLE ONLY docs_source_entries -- Name: docs_sources docs_sources_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY docs_sources +ALTER TABLE ONLY public.docs_sources ADD CONSTRAINT docs_sources_pkey PRIMARY KEY (id); @@ -681,7 +681,7 @@ ALTER TABLE ONLY docs_sources -- Name: hash_records hash_records_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY hash_records +ALTER TABLE ONLY public.hash_records ADD CONSTRAINT hash_records_pkey PRIMARY KEY (id); @@ -689,7 +689,7 @@ ALTER TABLE ONLY hash_records -- Name: identities identities_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY identities +ALTER TABLE ONLY public.identities ADD CONSTRAINT identities_pkey PRIMARY KEY (id); @@ -697,7 +697,7 @@ ALTER TABLE ONLY identities -- Name: kubernetes_clusters kubernetes_clusters_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY kubernetes_clusters +ALTER TABLE ONLY public.kubernetes_clusters ADD CONSTRAINT kubernetes_clusters_pkey PRIMARY KEY (id); @@ -705,7 +705,7 @@ ALTER TABLE ONLY kubernetes_clusters -- Name: kubernetes_groups kubernetes_groups_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY kubernetes_groups +ALTER TABLE ONLY public.kubernetes_groups ADD CONSTRAINT kubernetes_groups_pkey PRIMARY KEY (id); @@ -713,7 +713,7 @@ ALTER TABLE ONLY kubernetes_groups -- Name: kubernetes_namespaces kubernetes_namespaces_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY kubernetes_namespaces +ALTER TABLE ONLY public.kubernetes_namespaces ADD CONSTRAINT kubernetes_namespaces_pkey PRIMARY KEY (id); @@ -721,7 +721,7 @@ ALTER TABLE ONLY kubernetes_namespaces -- Name: kubernetes_tokens kubernetes_tokens_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY kubernetes_tokens +ALTER TABLE ONLY public.kubernetes_tokens ADD CONSTRAINT kubernetes_tokens_pkey PRIMARY KEY (id); @@ -729,7 +729,7 @@ ALTER TABLE ONLY kubernetes_tokens -- Name: platform_themes platform_themes_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY platform_themes +ALTER TABLE ONLY public.platform_themes ADD CONSTRAINT platform_themes_pkey PRIMARY KEY (id); @@ -737,7 +737,7 @@ ALTER TABLE ONLY platform_themes -- Name: projects projects_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY projects +ALTER TABLE ONLY public.projects ADD CONSTRAINT projects_pkey PRIMARY KEY (id); @@ -745,7 +745,7 @@ ALTER TABLE ONLY projects -- Name: qa_entries qa_entries_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY qa_entries +ALTER TABLE ONLY public.qa_entries ADD CONSTRAINT qa_entries_pkey PRIMARY KEY (id); @@ -753,7 +753,7 @@ ALTER TABLE ONLY qa_entries -- Name: read_marks read_marks_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY read_marks +ALTER TABLE ONLY public.read_marks ADD CONSTRAINT read_marks_pkey PRIMARY KEY (id); @@ -761,7 +761,7 @@ ALTER TABLE ONLY read_marks -- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY schema_migrations +ALTER TABLE ONLY public.schema_migrations ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version); @@ -769,7 +769,7 @@ ALTER TABLE ONLY schema_migrations -- Name: services services_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY services +ALTER TABLE ONLY public.services ADD CONSTRAINT services_pkey PRIMARY KEY (id); @@ -777,7 +777,7 @@ ALTER TABLE ONLY services -- Name: support_request_templates support_request_templates_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY support_request_templates +ALTER TABLE ONLY public.support_request_templates ADD CONSTRAINT support_request_templates_pkey PRIMARY KEY (id); @@ -785,7 +785,7 @@ ALTER TABLE ONLY support_request_templates -- Name: users user_email; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY users +ALTER TABLE ONLY public.users ADD CONSTRAINT user_email UNIQUE (email); @@ -793,7 +793,7 @@ ALTER TABLE ONLY users -- Name: user_flags user_flags_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY user_flags +ALTER TABLE ONLY public.user_flags ADD CONSTRAINT user_flags_pkey PRIMARY KEY (id); @@ -801,7 +801,7 @@ ALTER TABLE ONLY user_flags -- Name: users users_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- -ALTER TABLE ONLY users +ALTER TABLE ONLY public.users ADD CONSTRAINT users_pkey PRIMARY KEY (id); @@ -809,434 +809,434 @@ ALTER TABLE ONLY users -- Name: delayed_jobs_priority; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX delayed_jobs_priority ON delayed_jobs USING btree (priority, run_at); +CREATE INDEX delayed_jobs_priority ON public.delayed_jobs USING btree (priority, run_at); -- -- Name: index_allocations_on_al_rec_type_and_al_rec_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_allocations_on_al_rec_type_and_al_rec_id ON allocations USING btree (allocation_receivable_type, allocation_receivable_id); +CREATE INDEX index_allocations_on_al_rec_type_and_al_rec_id ON public.allocations USING btree (allocation_receivable_type, allocation_receivable_id); -- -- Name: index_allocations_on_al_type_and_al_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_allocations_on_al_type_and_al_id ON allocations USING btree (allocatable_type, allocatable_id); +CREATE INDEX index_allocations_on_al_type_and_al_id ON public.allocations USING btree (allocatable_type, allocatable_id); -- -- Name: index_announcement_templates_on_shortname; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX index_announcement_templates_on_shortname ON announcement_templates USING btree (shortname); +CREATE UNIQUE INDEX index_announcement_templates_on_shortname ON public.announcement_templates USING btree (shortname); -- -- Name: index_announcement_templates_on_slug; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX index_announcement_templates_on_slug ON announcement_templates USING btree (slug); +CREATE UNIQUE INDEX index_announcement_templates_on_slug ON public.announcement_templates USING btree (slug); -- -- Name: index_announcements_on_is_global; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_announcements_on_is_global ON announcements USING btree (is_global); +CREATE INDEX index_announcements_on_is_global ON public.announcements USING btree (is_global); -- -- Name: index_announcements_on_level; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_announcements_on_level ON announcements USING btree (level); +CREATE INDEX index_announcements_on_level ON public.announcements USING btree (level); -- -- Name: index_announcements_on_original_template_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_announcements_on_original_template_id ON announcements USING btree (original_template_id); +CREATE INDEX index_announcements_on_original_template_id ON public.announcements USING btree (original_template_id); -- -- Name: index_announcements_on_publish_at; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_announcements_on_publish_at ON announcements USING btree (publish_at); +CREATE INDEX index_announcements_on_publish_at ON public.announcements USING btree (publish_at); -- -- Name: index_announcements_on_status; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_announcements_on_status ON announcements USING btree (status); +CREATE INDEX index_announcements_on_status ON public.announcements USING btree (status); -- -- Name: index_audits_on_associated_type_and_associated_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_audits_on_associated_type_and_associated_id ON audits USING btree (associated_type, associated_id); +CREATE INDEX index_audits_on_associated_type_and_associated_id ON public.audits USING btree (associated_type, associated_id); -- -- Name: index_audits_on_auditable_type_and_auditable_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_audits_on_auditable_type_and_auditable_id ON audits USING btree (auditable_type, auditable_id); +CREATE INDEX index_audits_on_auditable_type_and_auditable_id ON public.audits USING btree (auditable_type, auditable_id); -- -- Name: index_audits_on_created_at; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_audits_on_created_at ON audits USING btree (created_at); +CREATE INDEX index_audits_on_created_at ON public.audits USING btree (created_at); -- -- Name: index_audits_on_remote_ip; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_audits_on_remote_ip ON audits USING btree (remote_ip); +CREATE INDEX index_audits_on_remote_ip ON public.audits USING btree (remote_ip); -- -- Name: index_audits_on_request_uuid; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_audits_on_request_uuid ON audits USING btree (request_uuid); +CREATE INDEX index_audits_on_request_uuid ON public.audits USING btree (request_uuid); -- -- Name: index_audits_on_user_email; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_audits_on_user_email ON audits USING btree (user_email); +CREATE INDEX index_audits_on_user_email ON public.audits USING btree (user_email); -- -- Name: index_audits_on_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_audits_on_user_id ON audits USING btree (user_id); +CREATE INDEX index_audits_on_user_id ON public.audits USING btree (user_id); -- -- Name: index_audits_on_user_name; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_audits_on_user_name ON audits USING btree (user_name); +CREATE INDEX index_audits_on_user_name ON public.audits USING btree (user_name); -- -- Name: index_delayed_jobs_on_queue; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_delayed_jobs_on_queue ON delayed_jobs USING btree (queue); +CREATE INDEX index_delayed_jobs_on_queue ON public.delayed_jobs USING btree (queue); -- -- Name: index_docker_repos_on_name; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX index_docker_repos_on_name ON docker_repos USING btree (name); +CREATE UNIQUE INDEX index_docker_repos_on_name ON public.docker_repos USING btree (name); -- -- Name: index_docker_repos_on_service_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_docker_repos_on_service_id ON docker_repos USING btree (service_id); +CREATE INDEX index_docker_repos_on_service_id ON public.docker_repos USING btree (service_id); -- -- Name: index_docs_source_entries_on_docs_source_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_docs_source_entries_on_docs_source_id ON docs_source_entries USING btree (docs_source_id); +CREATE INDEX index_docs_source_entries_on_docs_source_id ON public.docs_source_entries USING btree (docs_source_id); -- -- Name: index_docs_sources_on_kind; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_docs_sources_on_kind ON docs_sources USING btree (kind); +CREATE INDEX index_docs_sources_on_kind ON public.docs_sources USING btree (kind); -- -- Name: index_hash_records_on_scope; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_hash_records_on_scope ON hash_records USING btree (scope); +CREATE INDEX index_hash_records_on_scope ON public.hash_records USING btree (scope); -- -- Name: index_identities_on_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_identities_on_user_id ON identities USING btree (user_id); +CREATE INDEX index_identities_on_user_id ON public.identities USING btree (user_id); -- -- Name: index_kubernetes_clusters_on_aliases; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_kubernetes_clusters_on_aliases ON kubernetes_clusters USING gin (aliases); +CREATE INDEX index_kubernetes_clusters_on_aliases ON public.kubernetes_clusters USING gin (aliases); -- -- Name: index_kubernetes_clusters_on_name; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX index_kubernetes_clusters_on_name ON kubernetes_clusters USING btree (name); +CREATE UNIQUE INDEX index_kubernetes_clusters_on_name ON public.kubernetes_clusters USING btree (name); -- -- Name: index_kubernetes_groups_on_is_privileged; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_kubernetes_groups_on_is_privileged ON kubernetes_groups USING btree (is_privileged); +CREATE INDEX index_kubernetes_groups_on_is_privileged ON public.kubernetes_groups USING btree (is_privileged); -- -- Name: index_kubernetes_groups_on_kind; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_kubernetes_groups_on_kind ON kubernetes_groups USING btree (kind); +CREATE INDEX index_kubernetes_groups_on_kind ON public.kubernetes_groups USING btree (kind); -- -- Name: index_kubernetes_groups_on_name; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX index_kubernetes_groups_on_name ON kubernetes_groups USING btree (name); +CREATE UNIQUE INDEX index_kubernetes_groups_on_name ON public.kubernetes_groups USING btree (name); -- -- Name: index_kubernetes_groups_on_restricted_to_clusters; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_kubernetes_groups_on_restricted_to_clusters ON kubernetes_groups USING gin (restricted_to_clusters); +CREATE INDEX index_kubernetes_groups_on_restricted_to_clusters ON public.kubernetes_groups USING gin (restricted_to_clusters); -- -- Name: index_kubernetes_groups_on_target; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_kubernetes_groups_on_target ON kubernetes_groups USING btree (target); +CREATE INDEX index_kubernetes_groups_on_target ON public.kubernetes_groups USING btree (target); -- -- Name: index_kubernetes_namespaces_on_cluster_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_kubernetes_namespaces_on_cluster_id ON kubernetes_namespaces USING btree (cluster_id); +CREATE INDEX index_kubernetes_namespaces_on_cluster_id ON public.kubernetes_namespaces USING btree (cluster_id); -- -- Name: index_kubernetes_namespaces_on_name_and_cluster_id; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX index_kubernetes_namespaces_on_name_and_cluster_id ON kubernetes_namespaces USING btree (name, cluster_id); +CREATE UNIQUE INDEX index_kubernetes_namespaces_on_name_and_cluster_id ON public.kubernetes_namespaces USING btree (name, cluster_id); -- -- Name: index_kubernetes_namespaces_on_service_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_kubernetes_namespaces_on_service_id ON kubernetes_namespaces USING btree (service_id); +CREATE INDEX index_kubernetes_namespaces_on_service_id ON public.kubernetes_namespaces USING btree (service_id); -- -- Name: index_kubernetes_tokens_on_cluster_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_kubernetes_tokens_on_cluster_id ON kubernetes_tokens USING btree (cluster_id); +CREATE INDEX index_kubernetes_tokens_on_cluster_id ON public.kubernetes_tokens USING btree (cluster_id); -- -- Name: index_kubernetes_tokens_on_groups; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_kubernetes_tokens_on_groups ON kubernetes_tokens USING gin (groups); +CREATE INDEX index_kubernetes_tokens_on_groups ON public.kubernetes_tokens USING gin (groups); -- -- Name: index_kubernetes_tokens_on_kind; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_kubernetes_tokens_on_kind ON kubernetes_tokens USING btree (kind); +CREATE INDEX index_kubernetes_tokens_on_kind ON public.kubernetes_tokens USING btree (kind); -- -- Name: index_kubernetes_tokens_on_project_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_kubernetes_tokens_on_project_id ON kubernetes_tokens USING btree (project_id); +CREATE INDEX index_kubernetes_tokens_on_project_id ON public.kubernetes_tokens USING btree (project_id); -- -- Name: index_kubernetes_tokens_on_token; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX index_kubernetes_tokens_on_token ON kubernetes_tokens USING btree (token); +CREATE UNIQUE INDEX index_kubernetes_tokens_on_token ON public.kubernetes_tokens USING btree (token); -- -- Name: index_kubernetes_tokens_on_tokenable_type_and_tokenable_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_kubernetes_tokens_on_tokenable_type_and_tokenable_id ON kubernetes_tokens USING btree (tokenable_type, tokenable_id); +CREATE INDEX index_kubernetes_tokens_on_tokenable_type_and_tokenable_id ON public.kubernetes_tokens USING btree (tokenable_type, tokenable_id); -- -- Name: index_kubernetes_tokens_on_uid; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX index_kubernetes_tokens_on_uid ON kubernetes_tokens USING btree (uid); +CREATE UNIQUE INDEX index_kubernetes_tokens_on_uid ON public.kubernetes_tokens USING btree (uid); -- -- Name: index_platform_themes_on_slug; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX index_platform_themes_on_slug ON platform_themes USING btree (slug); +CREATE UNIQUE INDEX index_platform_themes_on_slug ON public.platform_themes USING btree (slug); -- -- Name: index_platform_themes_on_title; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX index_platform_themes_on_title ON platform_themes USING btree (title); +CREATE UNIQUE INDEX index_platform_themes_on_title ON public.platform_themes USING btree (title); -- -- Name: index_project_memberships_on_project_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_project_memberships_on_project_id ON project_memberships USING btree (project_id); +CREATE INDEX index_project_memberships_on_project_id ON public.project_memberships USING btree (project_id); -- -- Name: index_project_memberships_on_project_id_and_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX index_project_memberships_on_project_id_and_user_id ON project_memberships USING btree (project_id, user_id); +CREATE UNIQUE INDEX index_project_memberships_on_project_id_and_user_id ON public.project_memberships USING btree (project_id, user_id); -- -- Name: index_project_memberships_on_user_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_project_memberships_on_user_id ON project_memberships USING btree (user_id); +CREATE INDEX index_project_memberships_on_user_id ON public.project_memberships USING btree (user_id); -- -- Name: index_projects_on_shortname; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX index_projects_on_shortname ON projects USING btree (shortname); +CREATE UNIQUE INDEX index_projects_on_shortname ON public.projects USING btree (shortname); -- -- Name: index_projects_on_slug; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX index_projects_on_slug ON projects USING btree (slug); +CREATE UNIQUE INDEX index_projects_on_slug ON public.projects USING btree (slug); -- -- Name: index_read_marks_on_readable_type_and_readable_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_read_marks_on_readable_type_and_readable_id ON read_marks USING btree (readable_type, readable_id); +CREATE INDEX index_read_marks_on_readable_type_and_readable_id ON public.read_marks USING btree (readable_type, readable_id); -- -- Name: index_read_marks_on_reader_type_and_reader_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_read_marks_on_reader_type_and_reader_id ON read_marks USING btree (reader_type, reader_id); +CREATE INDEX index_read_marks_on_reader_type_and_reader_id ON public.read_marks USING btree (reader_type, reader_id); -- -- Name: index_services_on_project_id; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_services_on_project_id ON services USING btree (project_id); +CREATE INDEX index_services_on_project_id ON public.services USING btree (project_id); -- -- Name: index_support_request_templates_on_git_hub_repo; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_support_request_templates_on_git_hub_repo ON support_request_templates USING btree (git_hub_repo); +CREATE INDEX index_support_request_templates_on_git_hub_repo ON public.support_request_templates USING btree (git_hub_repo); -- -- Name: index_support_request_templates_on_shortname; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX index_support_request_templates_on_shortname ON support_request_templates USING btree (shortname); +CREATE UNIQUE INDEX index_support_request_templates_on_shortname ON public.support_request_templates USING btree (shortname); -- -- Name: index_support_request_templates_on_slug; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX index_support_request_templates_on_slug ON support_request_templates USING btree (slug); +CREATE UNIQUE INDEX index_support_request_templates_on_slug ON public.support_request_templates USING btree (slug); -- -- Name: index_users_on_is_active; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_users_on_is_active ON users USING btree (is_active); +CREATE INDEX index_users_on_is_active ON public.users USING btree (is_active); -- -- Name: index_users_on_role; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX index_users_on_role ON users USING btree (role); +CREATE INDEX index_users_on_role ON public.users USING btree (role); -- -- Name: kg_search_description_idx; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX kg_search_description_idx ON kubernetes_groups USING gin (description gin_trgm_ops); +CREATE INDEX kg_search_description_idx ON public.kubernetes_groups USING gin (description public.gin_trgm_ops); -- -- Name: kg_search_name_idx; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX kg_search_name_idx ON kubernetes_groups USING gin (name gin_trgm_ops); +CREATE INDEX kg_search_name_idx ON public.kubernetes_groups USING gin (name public.gin_trgm_ops); -- -- Name: read_marks_reader_readable_index; Type: INDEX; Schema: public; Owner: - -- -CREATE UNIQUE INDEX read_marks_reader_readable_index ON read_marks USING btree (reader_id, reader_type, readable_type, readable_id); +CREATE UNIQUE INDEX read_marks_reader_readable_index ON public.read_marks USING btree (reader_id, reader_type, readable_type, readable_id); -- -- Name: users_search_email_idx; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX users_search_email_idx ON users USING gin (email gin_trgm_ops); +CREATE INDEX users_search_email_idx ON public.users USING gin (email public.gin_trgm_ops); -- -- Name: users_search_idx; Type: INDEX; Schema: public; Owner: - -- -CREATE INDEX users_search_idx ON users USING gin (name gin_trgm_ops); +CREATE INDEX users_search_idx ON public.users USING gin (name public.gin_trgm_ops); -- diff --git a/platform-hub-web/package.json b/platform-hub-web/package.json index 4abf9585..e63f4729 100644 --- a/platform-hub-web/package.json +++ b/platform-hub-web/package.json @@ -51,7 +51,7 @@ "babel-plugin-istanbul": "^2.0.1", "babel-polyfill": "^6.23.0", "babel-preset-es2015": "^6.22.0", - "browser-sync": "^2.18.13", + "browser-sync": "2.26.3", "browser-sync-spa": "^1.0.3", "chai": "^4.0.2", "css-loader": "^0.26.1", diff --git a/platform-hub-web/src/app/projects/projects-list.component.js b/platform-hub-web/src/app/projects/projects-list.component.js index f74b4196..64d4f8ee 100644 --- a/platform-hub-web/src/app/projects/projects-list.component.js +++ b/platform-hub-web/src/app/projects/projects-list.component.js @@ -3,15 +3,18 @@ export const ProjectsListComponent = { controller: ProjectsListController }; -function ProjectsListController(roleCheckerService, Projects) { +function ProjectsListController(roleCheckerService, Projects, Me, _) { 'ngInject'; const ctrl = this; ctrl.Projects = Projects; + ctrl.myProjects = []; + ctrl.notMyProjects = []; ctrl.loading = true; ctrl.isAdmin = false; + ctrl.memberships = []; init(); @@ -23,18 +26,66 @@ function ProjectsListController(roleCheckerService, Projects) { function loadProjects() { ctrl.loading = true; - Projects - .refresh() - .finally(() => { - ctrl.loading = false; + return Projects.getAll() + .then(projects => { + return Me.refresh().then(() => { + const currentUserId = Me.data.id; + return Promise.all(projects.map(projectIdto => { + return Projects.getMemberships(projectIdto.id); + })).then(memberships => { + ctrl.memberships = memberships; + + ctrl.myProjects = getMyProjects(projects, currentUserId, memberships); + ctrl.notMyProjects = getNotMyProjects(projects, currentUserId, memberships); + + ctrl.myProjects = _.orderBy(ctrl.myProjects, [project => project.name.toLowerCase()], ['asc']); + ctrl.notMyProjects = _.orderBy(ctrl.notMyProjects, [project => project.name.toLowerCase()], ['asc']); + + Projects.all = _.concat(ctrl.myProjects, ctrl.notMyProjects); + + ctrl.loading = false; + }); }); + }); + } + + function getMyProjects(allProjects, currentUserId, memberships) { + return _.chain(allProjects) + .zip(memberships) + .filter(projectsMembershipsPair => { + const membership = projectsMembershipsPair[1]; + return _.some(membership, {user: {id: currentUserId}}); + }) + .map(projectsMembershipsPair => { + const project = projectsMembershipsPair[0]; + project.isProjectTeamMember = true; + return projectsMembershipsPair; + }) + .unzip() + .head().value(); + } + + function getNotMyProjects(allProjects, currentUserId, memberships) { + return _.chain(allProjects) + .zip(memberships) + .filter(projectsMembershipsPair => { + const membership = projectsMembershipsPair[1]; + return !_.some(membership, {user: {id: currentUserId}}); + }) + .map(projectsMembershipsPair => { + const project = projectsMembershipsPair[0]; + project.isProjectTeamMember = false; + return projectsMembershipsPair; + }) + .unzip() + .head().value(); } function loadAdminStatus() { roleCheckerService - .hasHubRole('admin') - .then(hasRole => { - ctrl.isAdmin = hasRole; - }); + .hasHubRole('admin') + .then(hasRole => { + ctrl.isAdmin = hasRole; + }); } } diff --git a/platform-hub-web/src/app/projects/projects-list.component.spec.js b/platform-hub-web/src/app/projects/projects-list.component.spec.js new file mode 100644 index 00000000..a5977fc6 --- /dev/null +++ b/platform-hub-web/src/app/projects/projects-list.component.spec.js @@ -0,0 +1,111 @@ +import angular from 'angular'; +import 'angular-mocks'; +import sinon from 'sinon'; +import chai from 'chai'; +import 'chai/register-should'; +import sinonChai from 'sinon-chai'; +chai.use(sinonChai); +import _ from 'lodash'; + +import {ProjectsModule} from './projects.module'; + +describe('projects-list component', () => { + let sandbox = null; + let element = null; + let $componentController = null; + let $compile = null; + let $rootScope = null; + let $q = null; + let $httpBackend = null; + let $state = null; + let roleCheckerService = null; + let Projects = null; + + beforeEach(() => { + const moduleName = `${ProjectsModule}.ProjectsListComponent.spec`; + angular.module(moduleName, ['app']); + angular.mock.module(moduleName); + }); + + beforeEach(angular.mock.inject((_$compile_, _$rootScope_, _$q_, _$httpBackend_, _$state_, _roleCheckerService_, _Projects_, _$componentController_) => { + sandbox = sinon.sandbox.create(); + + $compile = _$compile_; + $componentController = _$componentController_; + $rootScope = _$rootScope_; + $q = _$q_; + $httpBackend = _$httpBackend_; + $state = _$state_; + roleCheckerService = _roleCheckerService_; + Projects = _Projects_; + + $httpBackend + .whenGET(/.+/) + .respond('{}'); + })); + + afterEach(() => { + element = null; + + sandbox.restore(); + }); + + function renderComponent() { + element = $compile('')($rootScope); + $rootScope.$digest(); + } + + function stubAdmin(result) { + sandbox + .stub(roleCheckerService, 'hasHubRole') + .withArgs('admin') + .usingPromise($q) + .resolves(result); + } + + beforeEach(() => { + sandbox.spy($state, 'go'); + sandbox.spy(Projects, 'getAll'); + }); + + it('should render projects page', () => { + renderComponent(); + expect(element).toContainElement('div.projects-list'); + }); + + describe('for a non-admin user', () => { + beforeEach(() => { + stubAdmin(false); + }); + + it('shows all projects with user prioritised', () => { + const ctrl = $componentController('projectsList'); + ctrl.myProjects = [{id: 'test1', shortname: 'Test1', name: 'Testing1', description: null, costCentreCode: null, isProjectTeamMember: true, membersCount: 1, createdAt: '2020-07-30T16:19:02Z', updatedAt: '2020-07-30T16:19:02Z'}]; + ctrl.notMyProjects = [{id: 'test2', shortname: 'Test2', name: 'Testing2', description: null, costCentreCode: null, isProjectTeamMember: false, membersCount: 0, createdAt: '2020-07-30T16:29:02Z', updatedAt: '2020-07-30T16:29:02Z'}]; + Projects.all = _.concat(ctrl.myProjects, ctrl.notMyProjects); + + expect(Projects.all[0].isProjectTeamMember).toBe(true); + expect(Projects.all[1].isProjectTeamMember).toBe(false); + expect(Projects.all).toEqual([{id: 'test1', shortname: 'Test1', name: 'Testing1', description: null, costCentreCode: null, isProjectTeamMember: true, membersCount: 1, createdAt: '2020-07-30T16:19:02Z', updatedAt: '2020-07-30T16:19:02Z'}, + {id: 'test2', shortname: 'Test2', name: 'Testing2', description: null, costCentreCode: null, isProjectTeamMember: false, membersCount: 0, createdAt: '2020-07-30T16:29:02Z', updatedAt: '2020-07-30T16:29:02Z'}]); + }); + }); + + describe('for an admin user', () => { + beforeEach(() => { + stubAdmin(true); + }); + + it('shows all projects with user prioritised', () => { + const ctrl = $componentController('projectsList'); + ctrl.myProjects = [{id: 'test1', shortname: 'Test1', name: 'Testing1', description: null, costCentreCode: null, isProjectTeamMember: true, membersCount: 1, createdAt: '2020-07-30T16:19:02Z', updatedAt: '2020-07-30T16:19:02Z'}]; + ctrl.notMyProjects = [{id: 'test2', shortname: 'Test2', name: 'Testing2', description: null, costCentreCode: null, isProjectTeamMember: false, membersCount: 0, createdAt: '2020-07-30T16:29:02Z', updatedAt: '2020-07-30T16:29:02Z'}]; + Projects.all = _.concat(ctrl.myProjects, ctrl.notMyProjects); + + expect(Projects.all[0].isProjectTeamMember).toBe(true); + expect(Projects.all[1].isProjectTeamMember).toBe(false); + expect(Projects.all).toEqual([{id: 'test1', shortname: 'Test1', name: 'Testing1', description: null, costCentreCode: null, isProjectTeamMember: true, membersCount: 1, createdAt: '2020-07-30T16:19:02Z', updatedAt: '2020-07-30T16:19:02Z'}, + {id: 'test2', shortname: 'Test2', name: 'Testing2', description: null, costCentreCode: null, isProjectTeamMember: false, membersCount: 0, createdAt: '2020-07-30T16:29:02Z', updatedAt: '2020-07-30T16:29:02Z'}]); + }); + }); +}); diff --git a/platform-hub-web/src/app/projects/projects-list.html b/platform-hub-web/src/app/projects/projects-list.html index c4b3ea2d..e870f810 100644 --- a/platform-hub-web/src/app/projects/projects-list.html +++ b/platform-hub-web/src/app/projects/projects-list.html @@ -17,14 +17,16 @@

- + - + {{p.name}} ({{p.shortname}}) + Member diff --git a/platform-hub-web/src/app/shared/model/projects.js b/platform-hub-web/src/app/shared/model/projects.js index f4bb4403..29a24b70 100644 --- a/platform-hub-web/src/app/shared/model/projects.js +++ b/platform-hub-web/src/app/shared/model/projects.js @@ -10,6 +10,7 @@ export const Projects = function ($timeout, $q, apiBackoffTimeMs, hubApiService, model.all = []; model.refresh = refresh; + model.getAll = hubApiService.getProjects; model.get = hubApiService.getProject; model.create = hubApiService.createProject; model.update = hubApiService.updateProject; From 56fed5ab2c4413f46bb417ffa0d01be61d45bf80 Mon Sep 17 00:00:00 2001 From: Rhodine Orleans-Lindsay Date: Wed, 9 Sep 2020 10:40:01 +0100 Subject: [PATCH 2/2] failing test for setting project admin role MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit project admins can make project admins.Tests passing failing test for unsetting project admin role project admins can demote project admins.Tests passing amended making and demoting project admin view updated puma and rack vulns Added rails vulns to Anchore whitelist fixing module conflict Moved project admin’s set_role test to set_role describe block. Project Admins see ‘Admin’ badges for projects of which they are admins, non-admin members see ‘Member’ badges. Refactored projects-list.component. Amended projects-list.component tests. --- .drone.yml | 2 +- platform-hub-api/Gemfile.lock | 6 +- platform-hub-api/app/models/ability.rb | 6 ++ .../controllers/projects_controller_spec.rb | 97 +++++++++++++++++++ platform-hub-web/package.json | 2 +- .../app/projects/projects-detail.component.js | 4 +- .../src/app/projects/projects-detail.html | 4 +- .../app/projects/projects-list.component.js | 47 +++------ .../projects/projects-list.component.spec.js | 71 ++++++++++++-- .../src/app/projects/projects-list.html | 5 +- 10 files changed, 194 insertions(+), 50 deletions(-) diff --git a/.drone.yml b/.drone.yml index 87b2cf74..bcc8d24a 100644 --- a/.drone.yml +++ b/.drone.yml @@ -127,7 +127,7 @@ pipeline: api_scan_image: image: quay.io/ukhomeofficedigital/anchore-submission:latest image_name: platform-hub-api:${DRONE_COMMIT_SHA} - whitelist: CVE-2019-5419,CVE-2019-5420,CVE-2020-8130,CVE-2020-11077,CVE-2020-11076,CVE-2020-5247,CVE-2019-16770 + whitelist: CVE-2019-5419,CVE-2019-5420,CVE-2020-8130,CVE-2020-11077,CVE-2020-11076,CVE-2020-5247,CVE-2019-16770,CVE-2020-8164,CVE-2020-8165,CVE-2020-8162,CVE-2019-5420 when: event: [push, tag] diff --git a/platform-hub-api/Gemfile.lock b/platform-hub-api/Gemfile.lock index cd16145c..f9d8f880 100644 --- a/platform-hub-api/Gemfile.lock +++ b/platform-hub-api/Gemfile.lock @@ -183,8 +183,8 @@ GEM activesupport (>= 4.2) arel (>= 6) public_suffix (3.0.3) - puma (3.10.0) - rack (2.0.7) + puma (3.12.6) + rack (2.2.3) rack-test (0.6.3) rack (>= 1.0) rails (5.0.7.2) @@ -335,4 +335,4 @@ RUBY VERSION ruby 2.3.8p459 BUNDLED WITH - 1.16.2 + 1.17.3 diff --git a/platform-hub-api/app/models/ability.rb b/platform-hub-api/app/models/ability.rb index 83595f59..b7b04871 100644 --- a/platform-hub-api/app/models/ability.rb +++ b/platform-hub-api/app/models/ability.rb @@ -26,6 +26,12 @@ def initialize(user) can :remove_membership, Project do |project| can_administer_project project, user end + can :set_role, Project do |project| + can_administer_project project, user + end + can :unset_role, Project do |project| + can_administer_project project, user + end can :administer_projects, Project do |project| can_administer_project project, user end diff --git a/platform-hub-api/spec/controllers/projects_controller_spec.rb b/platform-hub-api/spec/controllers/projects_controller_spec.rb index 94df1976..8a3e5bc3 100644 --- a/platform-hub-api/spec/controllers/projects_controller_spec.rb +++ b/platform-hub-api/spec/controllers/projects_controller_spec.rb @@ -638,6 +638,54 @@ def expect_result result end + context 'not a hub admin but is project admin of same project' do + before do + create :project_membership_as_admin, project: @project, user: current_user + end + + context 'when user is not a project team member' do + it 'should return a 400 Bad Request error' do + put :set_role, params: { id: @project.id, user_id: @user.id, role: role } + expect(response).to have_http_status(400) + end + end + + context 'when user is a project team member' do + before do + create :project_membership, project: @project, user: @user + end + + it 'should set the role accordingly' do + expect(ProjectMembership.exists?(project_id: @project.id, user_id: @user.id, role: role)).to be false + expect(Audit.count).to eq 0 + put :set_role, params: { id: @project.id, user_id: @user.id, role: role } + expect(response).to be_success + expect(json_response['role']).to eq role + expect(ProjectMembership.exists?(project_id: @project.id, user_id: @user.id, role: role)).to be true + expect(Audit.count).to eq 1 + audit = Audit.first + expect(audit.action).to eq 'set_role' + expect(audit.auditable.id).to eq @project.id + expect(audit.associated.id).to eq @user.id + expect(audit.user.id).to eq current_user_id + expect(audit.data['previous_role']).to eq nil + expect(audit.data['new_role']).to eq role + end + end + end + + context 'not a hub admin but is project admin of a different project' do + before do + another_project = create :project + create :project_membership_as_admin, project: another_project, user: current_user + end + + it 'should not be able to set the role - returning 403 Forbidden' do + put :set_role, params: { id: @project.id, user_id: @user.id, role: role } + expect(response).to have_http_status(403) + end + end + end end @@ -700,6 +748,55 @@ def expect_result result end + context 'not a hub admin but is project admin of same project' do + before do + create :project_membership_as_admin, project: @project, user: current_user + end + + context 'when user is not a project team member' do + it 'should return a 400 Bad Request error' do + put :unset_role, params: { id: @project.id, user_id: @user.id, role: role } + expect(response).to have_http_status(400) + end + end + + context 'when user is a project team member' do + before do + create :project_membership, project: @project, user: @user, role: role + end + + it 'should unset the role accordingly' do + expect(ProjectMembership.exists?(project_id: @project.id, user_id: @user.id, role: role)).to be true + expect(Audit.count).to eq 0 + delete :unset_role, params: { id: @project.id, user_id: @user.id, role: role } + expect(response).to be_success + expect(json_response['role']).to eq nil + expect(ProjectMembership.exists?(project_id: @project.id, user_id: @user.id, role: role)).to be false + expect(ProjectMembership.exists?(project_id: @project.id, user_id: @user.id, role: nil)).to be true + expect(Audit.count).to eq 1 + audit = Audit.first + expect(audit.action).to eq 'unset_role' + expect(audit.auditable.id).to eq @project.id + expect(audit.associated.id).to eq @user.id + expect(audit.user.id).to eq current_user_id + expect(audit.data['previous_role']).to eq role + expect(audit.data['new_role']).to eq nil + end + end + end + + context 'not a hub admin but is project admin of a different project' do + before do + another_project = create :project + create :project_membership_as_admin, project: another_project, user: current_user + end + + it 'should not be able to unset the role - returning 403 Forbidden' do + put :unset_role, params: { id: @project.id, user_id: @user.id, role: role } + expect(response).to have_http_status(403) + end + end + end end diff --git a/platform-hub-web/package.json b/platform-hub-web/package.json index e63f4729..4abf9585 100644 --- a/platform-hub-web/package.json +++ b/platform-hub-web/package.json @@ -51,7 +51,7 @@ "babel-plugin-istanbul": "^2.0.1", "babel-polyfill": "^6.23.0", "babel-preset-es2015": "^6.22.0", - "browser-sync": "2.26.3", + "browser-sync": "^2.18.13", "browser-sync-spa": "^1.0.3", "chai": "^4.0.2", "css-loader": "^0.26.1", diff --git a/platform-hub-web/src/app/projects/projects-detail.component.js b/platform-hub-web/src/app/projects/projects-detail.component.js index c11c5f09..c470807e 100644 --- a/platform-hub-web/src/app/projects/projects-detail.component.js +++ b/platform-hub-web/src/app/projects/projects-detail.component.js @@ -198,7 +198,7 @@ function ProjectsDetailController($rootScope, $q, $mdDialog, $state, roleChecker } function makeAdmin(membership, targetEvent) { - if (!ctrl.isAdmin) { + if (!ctrl.isAdmin && !ctrl.isProjectAdmin) { return; } @@ -225,7 +225,7 @@ function ProjectsDetailController($rootScope, $q, $mdDialog, $state, roleChecker } function demoteAdmin(membership, targetEvent) { - if (!ctrl.isAdmin) { + if (!ctrl.isAdmin && !ctrl.isProjectAdmin) { return; } diff --git a/platform-hub-web/src/app/projects/projects-detail.html b/platform-hub-web/src/app/projects/projects-detail.html index 7269fe11..c0f42199 100644 --- a/platform-hub-web/src/app/projects/projects-detail.html +++ b/platform-hub-web/src/app/projects/projects-detail.html @@ -137,14 +137,14 @@

{{m.user.email}}

Offboard GitHub - + Make admin - + diff --git a/platform-hub-web/src/app/projects/projects-list.component.js b/platform-hub-web/src/app/projects/projects-list.component.js index 64d4f8ee..7b4b13a3 100644 --- a/platform-hub-web/src/app/projects/projects-list.component.js +++ b/platform-hub-web/src/app/projects/projects-list.component.js @@ -9,12 +9,9 @@ function ProjectsListController(roleCheckerService, Projects, Me, _) { const ctrl = this; ctrl.Projects = Projects; - ctrl.myProjects = []; - ctrl.notMyProjects = []; ctrl.loading = true; ctrl.isAdmin = false; - ctrl.memberships = []; init(); @@ -33,15 +30,10 @@ function ProjectsListController(roleCheckerService, Projects, Me, _) { return Promise.all(projects.map(projectIdto => { return Projects.getMemberships(projectIdto.id); })).then(memberships => { - ctrl.memberships = memberships; + const myProjects = getProjects(projects, currentUserId, memberships, true); + const notMyProjects = getProjects(projects, currentUserId, memberships, false); - ctrl.myProjects = getMyProjects(projects, currentUserId, memberships); - ctrl.notMyProjects = getNotMyProjects(projects, currentUserId, memberships); - - ctrl.myProjects = _.orderBy(ctrl.myProjects, [project => project.name.toLowerCase()], ['asc']); - ctrl.notMyProjects = _.orderBy(ctrl.notMyProjects, [project => project.name.toLowerCase()], ['asc']); - - Projects.all = _.concat(ctrl.myProjects, ctrl.notMyProjects); + Projects.all = _.concat(myProjects, notMyProjects); ctrl.loading = false; }); @@ -49,36 +41,29 @@ function ProjectsListController(roleCheckerService, Projects, Me, _) { }); } - function getMyProjects(allProjects, currentUserId, memberships) { - return _.chain(allProjects) - .zip(memberships) - .filter(projectsMembershipsPair => { - const membership = projectsMembershipsPair[1]; - return _.some(membership, {user: {id: currentUserId}}); - }) - .map(projectsMembershipsPair => { - const project = projectsMembershipsPair[0]; - project.isProjectTeamMember = true; - return projectsMembershipsPair; - }) - .unzip() - .head().value(); - } - - function getNotMyProjects(allProjects, currentUserId, memberships) { + function getProjects(allProjects, currentUserId, memberships, myProjects) { return _.chain(allProjects) .zip(memberships) .filter(projectsMembershipsPair => { const membership = projectsMembershipsPair[1]; - return !_.some(membership, {user: {id: currentUserId}}); + const userIsProjectMember = _.some(membership, {user: {id: currentUserId}}); + return myProjects ? userIsProjectMember : !userIsProjectMember; }) .map(projectsMembershipsPair => { const project = projectsMembershipsPair[0]; - project.isProjectTeamMember = false; + project.isProjectTeamMember = myProjects; + if (myProjects) { + const membership = projectsMembershipsPair[1]; + if (_.some(membership, {user: {id: currentUserId}, role: 'admin'})) { + project.isProjectAdmin = true; + } + } return projectsMembershipsPair; }) .unzip() - .head().value(); + .head() + .orderBy([project => project.name.toLowerCase()], ['asc']) + .value(); } function loadAdminStatus() { diff --git a/platform-hub-web/src/app/projects/projects-list.component.spec.js b/platform-hub-web/src/app/projects/projects-list.component.spec.js index a5977fc6..2d2bfab0 100644 --- a/platform-hub-web/src/app/projects/projects-list.component.spec.js +++ b/platform-hub-web/src/app/projects/projects-list.component.spec.js @@ -80,14 +80,36 @@ describe('projects-list component', () => { it('shows all projects with user prioritised', () => { const ctrl = $componentController('projectsList'); - ctrl.myProjects = [{id: 'test1', shortname: 'Test1', name: 'Testing1', description: null, costCentreCode: null, isProjectTeamMember: true, membersCount: 1, createdAt: '2020-07-30T16:19:02Z', updatedAt: '2020-07-30T16:19:02Z'}]; - ctrl.notMyProjects = [{id: 'test2', shortname: 'Test2', name: 'Testing2', description: null, costCentreCode: null, isProjectTeamMember: false, membersCount: 0, createdAt: '2020-07-30T16:29:02Z', updatedAt: '2020-07-30T16:29:02Z'}]; - Projects.all = _.concat(ctrl.myProjects, ctrl.notMyProjects); + const myProjects = [{id: 'test1', shortname: 'Test1', name: 'Testing1', description: null, costCentreCode: null, isProjectTeamMember: true, membersCount: 1, createdAt: '2020-07-30T16:19:02Z', updatedAt: '2020-07-30T16:19:02Z'}]; + const notMyProjects = [{id: 'test2', shortname: 'Test2', name: 'Testing2', description: null, costCentreCode: null, isProjectTeamMember: false, membersCount: 0, createdAt: '2020-07-30T16:29:02Z', updatedAt: '2020-07-30T16:29:02Z'}]; + ctrl.Projects.all = _.concat(myProjects, notMyProjects); + renderComponent(); expect(Projects.all[0].isProjectTeamMember).toBe(true); expect(Projects.all[1].isProjectTeamMember).toBe(false); expect(Projects.all).toEqual([{id: 'test1', shortname: 'Test1', name: 'Testing1', description: null, costCentreCode: null, isProjectTeamMember: true, membersCount: 1, createdAt: '2020-07-30T16:19:02Z', updatedAt: '2020-07-30T16:19:02Z'}, {id: 'test2', shortname: 'Test2', name: 'Testing2', description: null, costCentreCode: null, isProjectTeamMember: false, membersCount: 0, createdAt: '2020-07-30T16:29:02Z', updatedAt: '2020-07-30T16:29:02Z'}]); + expect(element).toContainElement('md-card#projects'); + }); + + it(`shows a 'Member' badge for user projects`, () => { + const ctrl = $componentController('projectsList'); + const myProjects = [{id: 'test1', shortname: 'Test1', name: 'Testing1', description: null, costCentreCode: null, isProjectTeamMember: true, membersCount: 1, createdAt: '2020-07-30T16:19:02Z', updatedAt: '2020-07-30T16:19:02Z'}]; + const notMyProjects = []; + ctrl.Projects.all = _.concat(myProjects, notMyProjects); + + renderComponent(); + expect(element).toContainElement('small#member-badge'); + }); + + it(`does not show a 'Member' badge for non-user projects`, () => { + const ctrl = $componentController('projectsList'); + const myProjects = []; + const notMyProjects = [{id: 'test2', shortname: 'Test2', name: 'Testing2', description: null, costCentreCode: null, isProjectTeamMember: false, membersCount: 0, createdAt: '2020-07-30T16:29:02Z', updatedAt: '2020-07-30T16:29:02Z'}]; + ctrl.Projects.all = _.concat(myProjects, notMyProjects); + + renderComponent(); + expect(element).not.toContainElement('small#member-badge'); }); }); @@ -98,14 +120,47 @@ describe('projects-list component', () => { it('shows all projects with user prioritised', () => { const ctrl = $componentController('projectsList'); - ctrl.myProjects = [{id: 'test1', shortname: 'Test1', name: 'Testing1', description: null, costCentreCode: null, isProjectTeamMember: true, membersCount: 1, createdAt: '2020-07-30T16:19:02Z', updatedAt: '2020-07-30T16:19:02Z'}]; - ctrl.notMyProjects = [{id: 'test2', shortname: 'Test2', name: 'Testing2', description: null, costCentreCode: null, isProjectTeamMember: false, membersCount: 0, createdAt: '2020-07-30T16:29:02Z', updatedAt: '2020-07-30T16:29:02Z'}]; - Projects.all = _.concat(ctrl.myProjects, ctrl.notMyProjects); + const myProjects = [{id: 'test1', shortname: 'Test1', name: 'Testing1', description: null, costCentreCode: null, isProjectTeamMember: true, isProjectAdmin: false, membersCount: 1, createdAt: '2020-07-30T16:19:02Z', updatedAt: '2020-07-30T16:19:02Z'}]; + const notMyProjects = [{id: 'test2', shortname: 'Test2', name: 'Testing2', description: null, costCentreCode: null, isProjectTeamMember: false, isProjectAdmin: false, membersCount: 0, createdAt: '2020-07-30T16:29:02Z', updatedAt: '2020-07-30T16:29:02Z'}]; + ctrl.Projects.all = _.concat(myProjects, notMyProjects); + renderComponent(); expect(Projects.all[0].isProjectTeamMember).toBe(true); expect(Projects.all[1].isProjectTeamMember).toBe(false); - expect(Projects.all).toEqual([{id: 'test1', shortname: 'Test1', name: 'Testing1', description: null, costCentreCode: null, isProjectTeamMember: true, membersCount: 1, createdAt: '2020-07-30T16:19:02Z', updatedAt: '2020-07-30T16:19:02Z'}, - {id: 'test2', shortname: 'Test2', name: 'Testing2', description: null, costCentreCode: null, isProjectTeamMember: false, membersCount: 0, createdAt: '2020-07-30T16:29:02Z', updatedAt: '2020-07-30T16:29:02Z'}]); + expect(Projects.all).toEqual([{id: 'test1', shortname: 'Test1', name: 'Testing1', description: null, costCentreCode: null, isProjectTeamMember: true, isProjectAdmin: false, membersCount: 1, createdAt: '2020-07-30T16:19:02Z', updatedAt: '2020-07-30T16:19:02Z'}, + {id: 'test2', shortname: 'Test2', name: 'Testing2', description: null, costCentreCode: null, isProjectTeamMember: false, isProjectAdmin: false, membersCount: 0, createdAt: '2020-07-30T16:29:02Z', updatedAt: '2020-07-30T16:29:02Z'}]); + expect(element).toContainElement('md-card#projects'); + }); + + it(`shows a 'Member' badge for projects where user is a member but not a project admin `, () => { + const ctrl = $componentController('projectsList'); + const myProjects = [{id: 'test1', shortname: 'Test1', name: 'Testing1', description: null, costCentreCode: null, isProjectTeamMember: true, isProjectAdmin: false, membersCount: 1, createdAt: '2020-07-30T16:19:02Z', updatedAt: '2020-07-30T16:19:02Z'}]; + const notMyProjects = []; + ctrl.Projects.all = _.concat(myProjects, notMyProjects); + + renderComponent(); + expect(element).toContainElement('small#member-badge'); + }); + + it(`shows an 'Admin' badge for projects of which the user is a project admin `, () => { + const ctrl = $componentController('projectsList'); + const myProjects = [{id: 'test1', shortname: 'Test1', name: 'Testing1', description: null, costCentreCode: null, isProjectTeamMember: true, isProjectAdmin: true, membersCount: 1, createdAt: '2020-07-30T16:19:02Z', updatedAt: '2020-07-30T16:19:02Z'}]; + const notMyProjects = []; + ctrl.Projects.all = _.concat(myProjects, notMyProjects); + + renderComponent(); + expect(element).toContainElement('small#admin-badge'); + }); + + it(`does not show a 'Member' badge for non-user projects`, () => { + const ctrl = $componentController('projectsList'); + const myProjects = []; + const notMyProjects = [{id: 'test2', shortname: 'Test2', name: 'Testing2', description: null, costCentreCode: null, isProjectTeamMember: false, isProjectAdmin: false, membersCount: 0, createdAt: '2020-07-30T16:29:02Z', updatedAt: '2020-07-30T16:29:02Z'}]; + ctrl.Projects.all = _.concat(myProjects, notMyProjects); + + renderComponent(); + expect(element).not.toContainElement('small#member-badge'); + expect(element).not.toContainElement('small#admin-badge'); }); }); }); diff --git a/platform-hub-web/src/app/projects/projects-list.html b/platform-hub-web/src/app/projects/projects-list.html index e870f810..45babcad 100644 --- a/platform-hub-web/src/app/projects/projects-list.html +++ b/platform-hub-web/src/app/projects/projects-list.html @@ -17,7 +17,7 @@

- + @@ -26,7 +26,8 @@

{{p.name}} ({{p.shortname}}) - Member + Member + Admin