@appscode/design-system 1.0.43-alpha.74 → 1.0.43-alpha.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -735,6 +735,147 @@ $border_color_4: transparent transparent #585d6e transparent;
735
735
  }
736
736
  }
737
737
  }
738
+ // tooltip in vue-open-api
739
+ .tooltip {
740
+ display: block !important;
741
+ z-index: 10000;
742
+
743
+ &.is-button-info {
744
+ .tooltip-inner {
745
+ background: $ac-white;
746
+ color: $ac-primary;
747
+ border-radius: 4px;
748
+ padding: 5px 20px 4px;
749
+ box-shadow: $ac-shadow-1;
750
+ font-weight: 500;
751
+ font-size: 13px;
752
+ }
753
+
754
+ .tooltip-arrow {
755
+ width: 0;
756
+ height: 0;
757
+ border-style: solid;
758
+ position: absolute;
759
+ margin: 5px;
760
+ border-color: $ac-white;
761
+ }
762
+ }
763
+
764
+ &.is-errors-tooltip {
765
+ .tooltip-inner {
766
+ background: $ac-white;
767
+ color: $ac-danger;
768
+ border-radius: 4px;
769
+ padding: 5px 20px 4px;
770
+ box-shadow: $ac-shadow-1;
771
+ font-weight: 500;
772
+ font-size: 13px;
773
+
774
+ .errors-wrapper {
775
+ .error-element {
776
+ padding: 5px 0;
777
+ }
778
+ }
779
+ }
780
+
781
+ .tooltip-arrow {
782
+ width: 0;
783
+ height: 0;
784
+ border-style: solid;
785
+ position: absolute;
786
+ margin: 5px;
787
+ border-color: $ac-white;
788
+ }
789
+ }
790
+
791
+ &[x-placement^="top"] {
792
+ margin-bottom: 5px;
793
+
794
+ .tooltip-arrow {
795
+ border-width: 5px 5px 0 5px;
796
+ border-left-color: transparent !important;
797
+ border-right-color: transparent !important;
798
+ border-bottom-color: transparent !important;
799
+ bottom: -5px;
800
+ left: calc(50% - 5px);
801
+ margin-top: 0;
802
+ margin-bottom: 0;
803
+ }
804
+ }
805
+
806
+ &[x-placement^="bottom"] {
807
+ margin-top: 5px;
808
+
809
+ .tooltip-arrow {
810
+ border-width: 0 5px 5px 5px;
811
+ border-left-color: transparent !important;
812
+ border-right-color: transparent !important;
813
+ border-top-color: transparent !important;
814
+ top: -5px;
815
+ left: calc(50% - 5px);
816
+ margin-top: 0;
817
+ margin-bottom: 0;
818
+ }
819
+ }
820
+
821
+ &[x-placement^="right"] {
822
+ margin-left: 5px;
823
+
824
+ .tooltip-arrow {
825
+ border-width: 5px 5px 5px 0;
826
+ border-left-color: transparent !important;
827
+ border-top-color: transparent !important;
828
+ border-bottom-color: transparent !important;
829
+ left: -5px;
830
+ top: calc(50% - 5px);
831
+ margin-left: 0;
832
+ margin-right: 0;
833
+ }
834
+ }
835
+
836
+ &[x-placement^="left"] {
837
+ margin-right: 5px;
838
+
839
+ .tooltip-arrow {
840
+ border-width: 5px 0 5px 5px;
841
+ border-top-color: transparent !important;
842
+ border-right-color: transparent !important;
843
+ border-bottom-color: transparent !important;
844
+ right: -5px;
845
+ top: calc(50% - 5px);
846
+ margin-left: 0;
847
+ margin-right: 0;
848
+ }
849
+ }
850
+
851
+ &.popover {
852
+ $color: #f9f9f9;
853
+
854
+ .popover-inner {
855
+ background: $color;
856
+ color: black;
857
+ padding: 24px;
858
+ border-radius: 4px;
859
+ box-shadow: $ac-shadow-1;
860
+ }
861
+
862
+ .popover-arrow {
863
+ border-color: $color;
864
+ }
865
+ }
866
+
867
+ &[aria-hidden="true"] {
868
+ visibility: hidden;
869
+ opacity: 0;
870
+ transition: opacity 0.15s, visibility 0.15s;
871
+ }
872
+
873
+ &[aria-hidden="false"] {
874
+ visibility: visible;
875
+ opacity: 1;
876
+ transition: opacity 0.15s;
877
+ }
878
+ }
738
879
 
739
880
  // Customize tooltip end
740
881
 
@@ -61,7 +61,7 @@
61
61
  position: absolute;
62
62
  content: "";
63
63
  left: 27px;
64
- top: 5px;
64
+ top: 10px;
65
65
  width: 1px;
66
66
  height: calc(100% - 20px);
67
67
  border: 1px dashed $ac-white-light;
@@ -0,0 +1,98 @@
1
+ .vue-schema-form-array {
2
+ .nested-body {
3
+ // margin-bottom: 15px;
4
+ display: flex;
5
+
6
+ .form-left-item {
7
+ margin-right: 10px;
8
+ width: calc(100% - 92px);
9
+ }
10
+ }
11
+ }
12
+
13
+ .nested-header {
14
+ .tabs.ac-tabs {
15
+ margin-bottom: 0;
16
+ opacity: 0;
17
+ visibility: hidden;
18
+ transition: 0.3s ease-in-out;
19
+ }
20
+
21
+ &:hover {
22
+ .tabs.ac-tabs {
23
+ opacity: 1;
24
+ visibility: visible;
25
+ }
26
+ }
27
+ }
28
+
29
+ .vue-openapi-form {
30
+ margin-left: -20px;
31
+ .is-warning {
32
+ font-size: 12px;
33
+ color: #ea3d2f;
34
+ padding-left: 10px;
35
+ }
36
+
37
+ .ac-nested-elements {
38
+ &:first-child {
39
+ margin-left: 0;
40
+ }
41
+
42
+ .nested-body {
43
+ padding-left: 0px;
44
+ }
45
+
46
+ .nested-header {
47
+ width: 100%;
48
+ }
49
+ }
50
+
51
+ .ac-single-switch {
52
+ margin-left: -15px;
53
+ }
54
+
55
+ .ac-single-input {
56
+ margin-left: 25px;
57
+
58
+ &:last-child {
59
+ margin-bottom: 15px;
60
+ }
61
+ }
62
+ }
63
+
64
+ .vue-form-scema-body {
65
+ .left-content {
66
+ width: 650px;
67
+ background-color: $ac-white-lighter;
68
+ padding: 30px;
69
+ }
70
+
71
+ .right-content {
72
+ width: 100%;
73
+ margin-top: 30px;
74
+ }
75
+ }
76
+
77
+ .v-tooltip-open {
78
+ background-color: $ac-white;
79
+ }
80
+
81
+ .ac-nested-elements::after {
82
+ top: 25px;
83
+ width: 1px;
84
+ height: calc(100% - 50px);
85
+ }
86
+
87
+ .ac-nested-elements::before {
88
+ bottom: 12px;
89
+ }
90
+
91
+ .is-collapsed {
92
+ &.ac-nested-elements::before,
93
+ &.ac-nested-elements::after {
94
+ display: none;
95
+ }
96
+ }
97
+
98
+ // for vue-tooltip
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appscode/design-system",
3
- "version": "1.0.43-alpha.74",
3
+ "version": "1.0.43-alpha.78",
4
4
  "description": "A design system for Appscode websites and dashboards made using Bulma",
5
5
  "main": "main.scss",
6
6
  "scripts": {
@@ -37,7 +37,10 @@
37
37
  <!-- modal body end -->
38
38
 
39
39
  <!-- modal footer start -->
40
- <div class="ac-modal-footer action-footer">
40
+ <div class="ac-modal-footer action-footer is-flex is-align-items-center is-justify-content-space-between">
41
+ <div>
42
+ <slot name="modal-footer-left" />
43
+ </div>
41
44
  <buttons class="has-text-right is-block">
42
45
  <slot name="modal-footer-controls" />
43
46
  </buttons>
@@ -0,0 +1,173 @@
1
+ <template>
2
+ <div class="is-cluster-logo" v-if="sidebarCollapsed">
3
+ <img
4
+ width="40"
5
+ :src="getProviderIcon(selectedCluster && selectedCluster.provider)"
6
+ alt=""
7
+ />
8
+ </div>
9
+ <multiselect
10
+ v-else
11
+ v-model="selectedCluster"
12
+ placeholder="Selected Cluster"
13
+ label="name"
14
+ track-by="uid"
15
+ :options="options"
16
+ :allow-empty="false"
17
+ deselectLabel=""
18
+ selectLabel=""
19
+ selectedLabel=""
20
+ >
21
+ <template slot="singleLabel" slot-scope="props">
22
+ <div class="is-flex is-align-items-center">
23
+ <img
24
+ :src="getProviderIcon(props.option.provider)"
25
+ alt="No cluster selected"
26
+ /><span
27
+ ><span>{{ props.option.displayName }}</span></span
28
+ >
29
+ </div>
30
+ </template>
31
+ <template slot="option" slot-scope="props">
32
+ <div class="is-flex is-align-items-center">
33
+ <img
34
+ class="mr-15"
35
+ :src="getProviderIcon(props.option.provider)"
36
+ alt="No cluster selected"
37
+ />
38
+ <div>
39
+ <p>{{ props.option.displayName }}</p>
40
+ <p class="location">{{ props.option.location }}</p>
41
+ </div>
42
+ </div>
43
+ </template>
44
+ </multiselect>
45
+ </template>
46
+
47
+ <script>
48
+ import { mapGetters } from "vuex";
49
+ export default {
50
+ props: {
51
+ sidebarCollapsed: {
52
+ type: Boolean,
53
+ default: false,
54
+ },
55
+ mouseHover: {
56
+ type: Boolean,
57
+ default: false,
58
+ },
59
+ username: {
60
+ type: String,
61
+ default: "",
62
+ },
63
+ imagePath: {
64
+ type: Object,
65
+ default: () => ({}),
66
+ },
67
+ value: {
68
+ type: Object,
69
+ default: () => ({}),
70
+ },
71
+ },
72
+
73
+ components: {
74
+ Multiselect: () => import("vue-multiselect"),
75
+ },
76
+
77
+ data() {
78
+ return {
79
+ selectedCluster: null,
80
+ clusters: [],
81
+ options: [],
82
+ };
83
+ },
84
+
85
+ computed: {
86
+ selectClusterOptions() {
87
+ return this.clusters
88
+ .filter(
89
+ (cluster) =>
90
+ cluster.status.phase === "Connected" ||
91
+ cluster.status.phase === "PrivateConnected"
92
+ )
93
+ .map((cluster) => {
94
+ return {
95
+ name: cluster.spec.name,
96
+ displayName: cluster.spec.displayName,
97
+ provider: cluster.spec.provider,
98
+ uid: cluster.spec.uid,
99
+ location: cluster.spec.location,
100
+ };
101
+ });
102
+ },
103
+ },
104
+
105
+ methods: {
106
+ async checkStatus(clusterName) {
107
+ try {
108
+ await this.$axios.get(
109
+ `/clusters/${this.username}/${clusterName}/status`
110
+ );
111
+ return true;
112
+ } catch (err) {
113
+ return false;
114
+ }
115
+ },
116
+ async getClusters() {
117
+ if (this.username) {
118
+ const url = `/clusters/${this.username}`;
119
+
120
+ try {
121
+ const resp = await this.$axios.get(url);
122
+ this.clusters = (resp.data && resp.data.items) || [];
123
+
124
+ // preselect the cluster
125
+ const selectedCluster = this.clusters.find(
126
+ (cluster) => cluster.spec.name === this.$route.params.cluster
127
+ );
128
+ this.selectedCluster = {
129
+ name: selectedCluster.spec.name,
130
+ displayName: selectedCluster.spec.displayName,
131
+ provider: selectedCluster.spec.provider,
132
+ uid: selectedCluster.spec.uid,
133
+ location: selectedCluster.spec.location,
134
+ };
135
+ } catch (e) {
136
+ console.log(e);
137
+ }
138
+ }
139
+ },
140
+
141
+ getProviderIcon(provider) {
142
+ return this.imagePath[provider] || this.imagePath["default"];
143
+ },
144
+ },
145
+
146
+ created() {
147
+ this.getClusters();
148
+ },
149
+
150
+ watch: {
151
+ value: {
152
+ deep: true,
153
+ immediate: true,
154
+ handler(n) {
155
+ this.selectedCluster = n;
156
+ },
157
+ },
158
+ selectClusterOptions: {
159
+ deep: true,
160
+ immediate: true,
161
+ async handler(list) {
162
+ this.options = [];
163
+ if (list) {
164
+ list.forEach(async (item) => {
165
+ const resp = await this.checkStatus(item.name);
166
+ if (resp) this.options.push(item);
167
+ });
168
+ }
169
+ },
170
+ },
171
+ },
172
+ };
173
+ </script>
@@ -37,7 +37,10 @@
37
37
  <!-- modal body end -->
38
38
 
39
39
  <!-- modal footer start -->
40
- <div class="ac-modal-footer action-footer">
40
+ <div class="ac-modal-footer action-footer is-flex is-align-items-center is-justify-content-space-between">
41
+ <div>
42
+ <slot name="modal-footer-left" />
43
+ </div>
41
44
  <buttons class="has-text-right is-block">
42
45
  <slot name="modal-footer-controls" />
43
46
  </buttons>
@@ -0,0 +1,173 @@
1
+ <template>
2
+ <div class="is-cluster-logo" v-if="sidebarCollapsed">
3
+ <img
4
+ width="40"
5
+ :src="getProviderIcon(selectedCluster && selectedCluster.provider)"
6
+ alt=""
7
+ />
8
+ </div>
9
+ <multiselect
10
+ v-else
11
+ v-model="selectedCluster"
12
+ placeholder="Selected Cluster"
13
+ label="name"
14
+ track-by="uid"
15
+ :options="options"
16
+ :allow-empty="false"
17
+ deselectLabel=""
18
+ selectLabel=""
19
+ selectedLabel=""
20
+ >
21
+ <template slot="singleLabel" slot-scope="props">
22
+ <div class="is-flex is-align-items-center">
23
+ <img
24
+ :src="getProviderIcon(props.option.provider)"
25
+ alt="No cluster selected"
26
+ /><span
27
+ ><span>{{ props.option.displayName }}</span></span
28
+ >
29
+ </div>
30
+ </template>
31
+ <template slot="option" slot-scope="props">
32
+ <div class="is-flex is-align-items-center">
33
+ <img
34
+ class="mr-15"
35
+ :src="getProviderIcon(props.option.provider)"
36
+ alt="No cluster selected"
37
+ />
38
+ <div>
39
+ <p>{{ props.option.displayName }}</p>
40
+ <p class="location">{{ props.option.location }}</p>
41
+ </div>
42
+ </div>
43
+ </template>
44
+ </multiselect>
45
+ </template>
46
+
47
+ <script>
48
+ import { defineComponent, defineAsyncComponent } from "vue";
49
+ export default defineComponent({
50
+ props: {
51
+ sidebarCollapsed: {
52
+ type: Boolean,
53
+ default: false,
54
+ },
55
+ mouseHover: {
56
+ type: Boolean,
57
+ default: false,
58
+ },
59
+ username: {
60
+ type: String,
61
+ default: "",
62
+ },
63
+ imagePath: {
64
+ type: Object,
65
+ default: () => ({}),
66
+ },
67
+ value: {
68
+ type: Object,
69
+ default: () => ({}),
70
+ },
71
+ },
72
+
73
+ components: {
74
+ Multiselect: () => import("vue-multiselect"),
75
+ },
76
+
77
+ data() {
78
+ return {
79
+ selectedCluster: null,
80
+ clusters: [],
81
+ options: [],
82
+ };
83
+ },
84
+
85
+ computed: {
86
+ selectClusterOptions() {
87
+ return this.clusters
88
+ .filter(
89
+ (cluster) =>
90
+ cluster.status.phase === "Connected" ||
91
+ cluster.status.phase === "PrivateConnected"
92
+ )
93
+ .map((cluster) => {
94
+ return {
95
+ name: cluster.spec.name,
96
+ displayName: cluster.spec.displayName,
97
+ provider: cluster.spec.provider,
98
+ uid: cluster.spec.uid,
99
+ location: cluster.spec.location,
100
+ };
101
+ });
102
+ },
103
+ },
104
+
105
+ methods: {
106
+ async checkStatus(clusterName) {
107
+ try {
108
+ await this.$axios.get(
109
+ `/clusters/${this.username}/${clusterName}/status`
110
+ );
111
+ return true;
112
+ } catch (err) {
113
+ return false;
114
+ }
115
+ },
116
+ async getClusters() {
117
+ if (this.username) {
118
+ const url = `/clusters/${this.username}`;
119
+
120
+ try {
121
+ const resp = await this.$axios.get(url);
122
+ this.clusters = (resp.data && resp.data.items) || [];
123
+
124
+ // preselect the cluster
125
+ const selectedCluster = this.clusters.find(
126
+ (cluster) => cluster.spec.name === this.$route.params.cluster
127
+ );
128
+ this.selectedCluster = {
129
+ name: selectedCluster.spec.name,
130
+ displayName: selectedCluster.spec.displayName,
131
+ provider: selectedCluster.spec.provider,
132
+ uid: selectedCluster.spec.uid,
133
+ location: selectedCluster.spec.location,
134
+ };
135
+ } catch (e) {
136
+ console.log(e);
137
+ }
138
+ }
139
+ },
140
+
141
+ getProviderIcon(provider) {
142
+ return this.imagePath[provider] || this.imagePath["default"];
143
+ },
144
+ },
145
+
146
+ created() {
147
+ this.getClusters();
148
+ },
149
+
150
+ watch: {
151
+ value: {
152
+ deep: true,
153
+ immediate: true,
154
+ handler(n) {
155
+ this.selectedCluster = n;
156
+ },
157
+ },
158
+ selectClusterOptions: {
159
+ deep: true,
160
+ immediate: true,
161
+ async handler(list) {
162
+ this.options = [];
163
+ if (list) {
164
+ list.forEach(async (item) => {
165
+ const resp = await this.checkStatus(item.name);
166
+ if (resp) this.options.push(item);
167
+ });
168
+ }
169
+ },
170
+ },
171
+ },
172
+ });
173
+ </script>