{{ icon }}
diff --git a/src/openssf-dashboard/shared/components/button/button.component.scss b/src/openssf-dashboard/shared/components/button/button.component.scss
index 58caba2..9f020b6 100644
--- a/src/openssf-dashboard/shared/components/button/button.component.scss
+++ b/src/openssf-dashboard/shared/components/button/button.component.scss
@@ -16,6 +16,7 @@
transition: var(--default-transition);
cursor: pointer;
+ &.active,
&:not(.disabled):hover {
opacity: 1;
background-color: rgba(255, 255, 255, .5);
diff --git a/src/openssf-dashboard/shared/components/button/button.component.ts b/src/openssf-dashboard/shared/components/button/button.component.ts
index 50e63ef..09f9314 100644
--- a/src/openssf-dashboard/shared/components/button/button.component.ts
+++ b/src/openssf-dashboard/shared/components/button/button.component.ts
@@ -32,6 +32,7 @@ export class ButtonComponent {
readonly icon = input
(undefined);
readonly label = input(undefined);
readonly disabled = input(false);
+ readonly active = input(false);
readonly clicked = output();
/**
diff --git a/src/openssf-dashboard/shared/components/multi-toggle-button/multi-toggle-button.component.html b/src/openssf-dashboard/shared/components/multi-toggle-button/multi-toggle-button.component.html
new file mode 100644
index 0000000..5b0f21e
--- /dev/null
+++ b/src/openssf-dashboard/shared/components/multi-toggle-button/multi-toggle-button.component.html
@@ -0,0 +1,26 @@
+
+
+@if (optionsVisible()) {
+
+
+ @for (option of items(); track option.name) {
+
+
+
+
+
+
+ @if (option.active) {
+ check_circle
+ } @else {
+ do_not_disturb_on
+ }
+
+
+ }
+
+
+}
diff --git a/src/openssf-dashboard/shared/components/multi-toggle-button/multi-toggle-button.component.scss b/src/openssf-dashboard/shared/components/multi-toggle-button/multi-toggle-button.component.scss
new file mode 100644
index 0000000..006a7cc
--- /dev/null
+++ b/src/openssf-dashboard/shared/components/multi-toggle-button/multi-toggle-button.component.scss
@@ -0,0 +1,49 @@
+.container {
+ position: relative;
+ background-color: green;
+
+ .options {
+ position: absolute;
+ top: 0;
+ right: 0;
+ border-radius: var(--default-border-radius);
+ box-shadow: var(--default-box-shadow);
+ background-color: var(--ui-primary-color);
+ padding: .3rem;
+ width: 300px;
+ z-index: 99999;
+ user-select: none;
+
+ > div {
+ display: flex;
+ gap: 1rem;
+ padding: 1rem;
+ border-radius: var(--default-border-radius);
+ transition: var(--default-transition);
+ cursor: pointer;
+
+ &:hover {
+ background-color: rgba(0, 0, 0, .05);
+ }
+
+ > div {
+ display: flex;
+ align-items: center;
+ }
+
+ .name {
+ flex: 1;
+ }
+
+ .state {
+ .active {
+ color: green;
+ }
+
+ .not-active {
+ color: grey;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/openssf-dashboard/shared/components/multi-toggle-button/multi-toggle-button.component.ts b/src/openssf-dashboard/shared/components/multi-toggle-button/multi-toggle-button.component.ts
new file mode 100644
index 0000000..615495b
--- /dev/null
+++ b/src/openssf-dashboard/shared/components/multi-toggle-button/multi-toggle-button.component.ts
@@ -0,0 +1,78 @@
+/*---------------------------------------------------------------------------------------------
+ *
+ * Copyright (C) Codeplay Software Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *--------------------------------------------------------------------------------------------*/
+
+import { Component, HostListener, input, model, output, signal, WritableSignal } from '@angular/core';
+import { NgClass } from '@angular/common';
+import { ButtonComponent } from '../button/button.component';
+
+@Component({
+ selector: 'osd-multi-toggle-button',
+ standalone: true,
+ imports: [
+ ButtonComponent,
+ ],
+ templateUrl: './multi-toggle-button.component.html',
+ styleUrl: './multi-toggle-button.component.scss'
+})
+export class MultiToggleButtonComponent {
+ readonly items = model([]);
+ readonly itemChange = output();
+ readonly optionsVisible: WritableSignal = signal(false);
+
+ /**
+ * Called when a user clicks anywhere.
+ */
+ @HostListener('document:click', ['$event'])
+ documentClick() {
+ if (!this.optionsVisible()) {
+ return ;
+ }
+
+ this.optionsVisible.set(false);
+ }
+
+ /**
+ * Called when a user clicks on the button.
+ */
+ onButtonClicked(event: MouseEvent) {
+ event.stopPropagation();
+ this.optionsVisible.set(!this.optionsVisible());
+ }
+
+ /**
+ * Called when a user toggles an option.
+ * @param event
+ * @param option
+ */
+ onOptionToggled(event: MouseEvent, option: ToggleButtonItem): void {
+ event.stopPropagation();
+
+ option.active = !option.active;
+ this.itemChange.emit(option);
+ }
+}
+
+/**
+ * Public interface for the toggle button item.
+ */
+export interface ToggleButtonItem {
+ id: any
+ name: string
+ icon: string
+ active: boolean
+}
diff --git a/src/openssf-dashboard/shared/models/repository.model.ts b/src/openssf-dashboard/shared/models/repository.model.ts
index cbc1c90..5dbf242 100644
--- a/src/openssf-dashboard/shared/models/repository.model.ts
+++ b/src/openssf-dashboard/shared/models/repository.model.ts
@@ -27,5 +27,6 @@ export interface RepositoryModel {
lastUpdated: Date
stars: number
description: string
+ archived: boolean
scorecard?: ScorecardModel
}
diff --git a/src/openssf-dashboard/shared/services/repository-services/github.service.ts b/src/openssf-dashboard/shared/services/repository-services/github.service.ts
index 502824b..389cd2c 100644
--- a/src/openssf-dashboard/shared/services/repository-services/github.service.ts
+++ b/src/openssf-dashboard/shared/services/repository-services/github.service.ts
@@ -100,7 +100,8 @@ export class GithubService extends BaseRepositoryService {
url: repository['url'],
lastUpdated: new Date(repository['updated_at']),
stars: repository['stargazers_count'],
- description: repository['description'] ?? 'This repository has no description available.'
+ description: repository['description'] ?? 'This repository has no description available.',
+ archived: repository['archived']
});
}
diff --git a/src/openssf-dashboard/shared/services/transient-storage.service.ts b/src/openssf-dashboard/shared/services/transient-storage.service.ts
index aa1cafd..fa7ce6c 100644
--- a/src/openssf-dashboard/shared/services/transient-storage.service.ts
+++ b/src/openssf-dashboard/shared/services/transient-storage.service.ts
@@ -64,8 +64,12 @@ export class TransientStorage {
set(
key: string,
value: T,
- timeoutInDays: number
+ timeoutInDays?: number
) {
+ if (!timeoutInDays) {
+ timeoutInDays = 365;
+ }
+
const expires = new Date();
expires.setDate(expires.getDate() + timeoutInDays);
diff --git a/src/styles.scss b/src/styles.scss
index 8a05dc6..02856b2 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -5,9 +5,9 @@ html, body {
color: #111;
--default-transition: .2s all;
- --default-border-radius: 8px;
- --default-border-radius-large: 12px;
- --default-box-shadow: 2px 2px 5px 0 rgba(0, 0, 0, .12);
+ --default-border-radius: 7px;
+ --default-border-radius-large: 10px;
+ --default-box-shadow: 2px 2px 5px 0 rgba(0, 0, 0, .14);
--default-border: #ccc 1px solid;
--hint-color: #23064c;